New test.
[mono.git] / mcs / class / corlib / System.IO.IsolatedStorage / MoonIsolatedStorageFileStream.cs
index 4a0f926a938ddacf7f8e6dbb88627928d59f1dbc..23b90e52ce774808399a38cd380177afe128ba38 100644 (file)
@@ -5,6 +5,7 @@
 // 
 // Authors
 //      Miguel de Icaza (miguel@novell.com)
+//     Sebastien Pouliot  <sebastien@ximian.com>
 //
 // Copyright (C) 2007, 2008 Novell, Inc (http://www.novell.com)
 //
@@ -27,7 +28,7 @@
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
-#if NET_2_1
+#if MOONLIGHT
 using System;
 using System.IO;
 
@@ -37,7 +38,6 @@ namespace System.IO.IsolatedStorage {
        // * Silverlight allows extending to more than AvailableFreeSpace (by up to 1024 bytes).
        //   This looks like a safety buffer.
 
-       [MonoTODO ("this needs to be quota-enabled")]
        public class IsolatedStorageFileStream : FileStream {
 
                IsolatedStorageFile container;
@@ -76,101 +76,145 @@ namespace System.IO.IsolatedStorage {
 
                protected override void Dispose (bool disposing)
                {
+                       // no PreCheck required
                        base.Dispose (disposing);
                }
 
                public override void Flush ()
                {
+                       container.PreCheck ();
                        base.Flush ();
                }
 
                public override int Read (byte [] buffer, int offset, int count)
                {
+                       container.PreCheck ();
                        return base.Read (buffer, offset, count);
                }
 
                public override int ReadByte ()
                {
+                       container.PreCheck ();
                        return base.ReadByte ();
                }
 
                public override long Seek (long offset, SeekOrigin origin)
                {
+                       container.PreCheck ();
                        return base.Seek (offset, origin);
                }
 
                public override void SetLength (long value)
                {
-                       // if we're getting bigger then we must ensure we fit in the available free space of our container
-                       if (container.CanExtend (value - Length))
-                               throw new IsolatedStorageException ();
+                       container.PreCheck ();
+                       // don't worry about quota if we can't write to the stream, 
+                       // the base class will throw the expected NotSupportedException
+                       if (!base.CanWrite)
+                               return;
+
+                       // will that request put us in a position to grow *or shrink* the file ?
+                       // note: this can be negative, e.g. calling SetLength(0), so we can't call EnsureQuotaLimits directly
+                       if (!IsolatedStorage.CanExtend (value - Length))
+                               throw new IsolatedStorageException ("Requested size is larger than remaining quota allowance.");
 
                        base.SetLength (value);
                }
 
                public override void Write (byte [] buffer, int offset, int count)
                {
+                       container.PreCheck ();
+                       EnsureQuotaLimits (count);
                        base.Write (buffer, offset, count);
                }
 
                public override void WriteByte (byte value)
                {
+                       container.PreCheck ();
+                       EnsureQuotaLimits (1);
                        base.WriteByte (value);
                }
 
                public override bool CanRead {
                        get {
+                               // no PreCheck required
                                return base.CanRead;
                        }
                }
 
                public override bool CanSeek {
                        get {
+                               // no PreCheck required
                                return base.CanSeek;
                        }
                }
 
                public override bool CanWrite {
                        get {
+                               // no PreCheck required
                                return base.CanWrite;
                        }
                }
 
                public override long Length {
                        get {
+                               // FileStream ctor sometimes calls Length, i.e. before container is set
+                               if (container != null)
+                                       container.PreCheck ();
                                return base.Length;
                        }
                }
 
                public override long Position {
                        get {
+                               container.PreCheck ();
                                return base.Position;
                        }
-
                        set {
+                               container.PreCheck ();
                                base.Position = value;
                        }
                }
 
                public override IAsyncResult BeginRead (byte[] buffer, int offset, int numBytes, AsyncCallback userCallback, object stateObject)
                {
+                       container.PreCheck ();
                        return base.BeginRead (buffer, offset, numBytes, userCallback, stateObject);
                }
 
                public override IAsyncResult BeginWrite (byte[] buffer, int offset, int numBytes, AsyncCallback userCallback, object stateObject)
                {
+                       container.PreCheck ();
+                       EnsureQuotaLimits (numBytes);
                        return base.BeginWrite (buffer, offset, numBytes, userCallback, stateObject);
                }
 
                public override int EndRead (IAsyncResult asyncResult)
                {
+                       container.PreCheck ();
                        return base.EndRead (asyncResult);
                }
 
                public override void EndWrite (IAsyncResult asyncResult)
                {
+                       container.PreCheck ();
                        base.EndWrite (asyncResult);
                }
+
+               private void EnsureQuotaLimits (long request)
+               {
+                       // don't worry about quota if we can't write to the stream, 
+                       // the base class will throw the expected NotSupportedException
+                       if (!base.CanWrite)
+                               return;
+
+                       // will that request put us in a position to grow the file ?
+                       long grow = Position + request - Length;
+                       if (grow < 0)
+                               return;
+
+                       if (!IsolatedStorage.CanExtend (grow))
+                               throw new IsolatedStorageException ("Requested size is larger than remaining quota allowance.");
+               }
        }
 }
 #endif