2005-08-11 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / corlib / System.IO / FileStream.cs
index 26ea2cdc4650367499916b4b86a2a56bf8fea52c..945f995d682a83bf69cd8e2612f102eae1dcd7c8 100644 (file)
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-using System;
 using System.Collections;
 using System.Globalization;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Runtime.Remoting.Messaging;
+using System.Security.Permissions;
 using System.Threading;
 
 #if NET_2_0
@@ -59,6 +59,7 @@ namespace System.IO
                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 noBuffering)
                {
                        this.handle = MonoIO.InvalidHandle;
@@ -81,6 +82,8 @@ namespace System.IO
                                this.canseek = true;
                        } else {
                                this.canseek = false;
+                               noBuffering = true;
+                               bufferSize = 0;
                        }
 
                        this.handle = handle;
@@ -89,9 +92,6 @@ namespace System.IO
                        this.async = isAsync;
                        this.anonymous = false;
 
-                       if (isAsync && MonoIO.SupportsAsync)
-                               ThreadPool.BindHandle (handle);
-
                        InitBuffer (bufferSize, noBuffering);
 
                        /* Can't set append mode */
@@ -197,8 +197,7 @@ namespace System.IO
 
                        MonoIOError error;
 
-                       bool openAsync = (isAsync && MonoIO.SupportsAsync);
-                       this.handle = MonoIO.Open (name, mode, access, share, openAsync, out error);
+                       this.handle = MonoIO.Open (name, mode, access, share, false, out error);
                        if (handle == MonoIO.InvalidHandle) {
                                // don't leak the path information for isolated storage
                                string fname = (anonymous) ? Path.GetFileName (name) : name;
@@ -214,8 +213,6 @@ namespace System.IO
                        if (MonoIO.GetFileType (handle, out error) == MonoFileType.Disk) {
                                this.canseek = true;
                                this.async = isAsync;
-                               if (openAsync)
-                                       ThreadPool.BindHandle (handle);
                        } else {
                                this.canseek = false;
                                this.async = false;
@@ -279,7 +276,7 @@ namespace System.IO
                                if (handle == MonoIO.InvalidHandle)
                                        throw new ObjectDisposedException ("Stream has been closed");
 
-                               if (!canseek)
+                               if (!CanSeek)
                                        throw new NotSupportedException ("The stream does not support seeking");
 
                                // Buffered data might change the length of the stream
@@ -326,6 +323,8 @@ namespace System.IO
                }
 
                public virtual IntPtr Handle {
+                       [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
+                       [SecurityPermission (SecurityAction.InheritanceDemand, UnmanagedCode = true)]
                        get {
                                return handle;
                        }
@@ -333,6 +332,8 @@ namespace System.IO
 
 #if NET_2_0
                public virtual SafeFileHandle SafeFileHandle {
+                       [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
+                       [SecurityPermission (SecurityAction.InheritanceDemand, UnmanagedCode = true)]
                        get { throw new NotImplementedException (); }
                }
 #endif
@@ -373,6 +374,14 @@ namespace System.IO
                        if (buf_offset == buf_size)
                                FlushBuffer ();
 
+                       if (buf_size == 0) { // No buffering
+                               buf [0] = value;
+                               buf_dirty = true;
+                               buf_length = 1;
+                               FlushBuffer ();
+                               return;
+                       }
+
                        buf [buf_offset ++] = value;
                        if (buf_offset > buf_length)
                                buf_length = buf_offset;
@@ -475,28 +484,8 @@ namespace System.IO
                        if (!async)
                                return base.BeginRead (buffer, offset, count, cback, state);
 
-                       if (!MonoIO.SupportsAsync) {
-                               ReadDelegate r = new ReadDelegate (ReadInternal);
-                               return r.BeginInvoke (buffer, offset, count, cback, state);                     
-                       }
-
-                       FileStreamAsyncResult result = new FileStreamAsyncResult (cback, state);
-                       result.Count = count;
-                       result.OriginalCount = count;
-                       int buffered = ReadSegment (buffer, offset, count);
-                       if (buffered >= count) {
-                               result.SetComplete (null, buffered, true);
-                               return result;
-                       }
-                       
-                       result.Buffer = buffer;
-                       result.Offset = offset + buffered;
-                       result.Count -= buffered;
-                       
-                       KeepReference (result);
-                       MonoIO.BeginRead (handle, result);
-
-                       return result;
+                       ReadDelegate r = new ReadDelegate (ReadInternal);
+                       return r.BeginInvoke (buffer, offset, count, cback, state);                     
                }
                
                public override int EndRead (IAsyncResult async_result)
@@ -507,35 +496,15 @@ namespace System.IO
                        if (!async)
                                return base.EndRead (async_result);
 
-                       if (!MonoIO.SupportsAsync) {
-                               AsyncResult ares = async_result as AsyncResult;
-                               if (ares == null)
-                                       throw new ArgumentException ("Invalid IAsyncResult", "async_result");
-
-                               ReadDelegate r = ares.AsyncDelegate as ReadDelegate;
-                               if (r == null)
-                                       throw new ArgumentException ("Invalid IAsyncResult", "async_result");
-
-                               return r.EndInvoke (async_result);
-                       }
-
-                       FileStreamAsyncResult result = async_result as FileStreamAsyncResult;
-                       if (result == null || result.BytesRead == -1)
+                       AsyncResult ares = async_result as AsyncResult;
+                       if (ares == null)
                                throw new ArgumentException ("Invalid IAsyncResult", "async_result");
 
-                       RemoveReference (result);
-                       if (result.Done)
-                               throw new InvalidOperationException ("EndRead already called.");
-
-                       result.Done = true;
-                       if (!result.IsCompleted)
-                               result.AsyncWaitHandle.WaitOne ();
-
-                       if (result.Exception != null)
-                               throw result.Exception;
+                       ReadDelegate r = ares.AsyncDelegate as ReadDelegate;
+                       if (r == null)
+                               throw new ArgumentException ("Invalid IAsyncResult", "async_result");
 
-                       buf_start += result.BytesRead;
-                       return result.OriginalCount - result.Count + result.BytesRead;
+                       return r.EndInvoke (async_result);
                }
 
                public override void Write (byte[] src, int src_offset, int count)
@@ -624,8 +593,6 @@ namespace System.IO
                        if (!async)
                                return base.BeginWrite (buffer, offset, count, cback, state);
 
-                       byte [] bytes;
-                       int buffered = 0;
                        FileStreamAsyncResult result = new FileStreamAsyncResult (cback, state);
                        result.BytesRead = -1;
                        result.Count = count;
@@ -634,33 +601,13 @@ namespace System.IO
                        if (buf_dirty) {
                                MemoryStream ms = new MemoryStream ();
                                FlushBufferToStream (ms);
-                               buffered = (int) ms.Length;
                                ms.Write (buffer, offset, count);
-                               bytes = ms.GetBuffer ();
                                offset = 0;
                                count = (int) ms.Length;
-                       } else {
-                               bytes = buffer;
-                       }
-
-                       if (!MonoIO.SupportsAsync) {
-                               WriteDelegate w = new WriteDelegate (WriteInternal);
-                               return w.BeginInvoke (buffer, offset, count, cback, state);                     
                        }
 
-                       if (buffered >= count) {
-                               result.SetComplete (null, buffered, true);
-                               return result;
-                       }
-                       
-                       result.Buffer = buffer;
-                       result.Offset = offset;
-                       result.Count = count;
-                       
-                       KeepReference (result);
-                       MonoIO.BeginWrite (handle, result);
-
-                       return result;
+                       WriteDelegate w = new WriteDelegate (WriteInternal);
+                       return w.BeginInvoke (buffer, offset, count, cback, state);                     
                }
                
                public override void EndWrite (IAsyncResult async_result)
@@ -673,36 +620,16 @@ namespace System.IO
                                return;
                        }
 
-                       if (!MonoIO.SupportsAsync) {
-                               AsyncResult ares = async_result as AsyncResult;
-                               if (ares == null)
-                                       throw new ArgumentException ("Invalid IAsyncResult", "async_result");
-
-                               WriteDelegate w = ares.AsyncDelegate as WriteDelegate;
-                               if (w == null)
-                                       throw new ArgumentException ("Invalid IAsyncResult", "async_result");
-
-                               w.EndInvoke (async_result);
-                               return;
-                       }
-
-                       FileStreamAsyncResult result = async_result as FileStreamAsyncResult;
-                       if (result == null || result.BytesRead != -1)
+                       AsyncResult ares = async_result as AsyncResult;
+                       if (ares == null)
                                throw new ArgumentException ("Invalid IAsyncResult", "async_result");
 
-                       RemoveReference (result);
-                       if (result.Done)
-                               throw new InvalidOperationException ("EndWrite already called.");
-
-                       result.Done = true;
-                       if (!result.IsCompleted)
-                               result.AsyncWaitHandle.WaitOne ();
-
-                       if (result.Exception != null)
-                               throw result.Exception;
+                       WriteDelegate w = ares.AsyncDelegate as WriteDelegate;
+                       if (w == null)
+                               throw new ArgumentException ("Invalid IAsyncResult", "async_result");
 
-                       buf_start += result.Count;
-                       buf_offset = buf_length = 0;
+                       w.EndInvoke (async_result);
+                       return;
                }
 
                public override long Seek (long offset, SeekOrigin origin)
@@ -1056,30 +983,9 @@ namespace System.IO
                        buf_dirty = false;
                }
 
-               static void KeepReference (object o)
-               {
-                       lock (typeof (FileStream)) {
-                               if (asyncObjects == null)
-                                       asyncObjects = new Hashtable ();
-
-                               asyncObjects [o] = o;
-                       }
-               }
-               
-               static void RemoveReference (object o)
-               {
-                       lock (typeof (FileStream)) {
-                               if (asyncObjects == null)
-                                       return;
-
-                               asyncObjects.Remove (o);
-                       }
-               }
-
                // fields
 
                internal const int DefaultBufferSize = 8192;
-               private static Hashtable asyncObjects;
 
                private FileAccess access;
                private bool owner;