New tests.
[mono.git] / mcs / class / corlib / System.IO.IsolatedStorage / MoonIsolatedStorageFileStream.cs
index fe222b0830582929ddda7f06d816abaa27bad69f..23b90e52ce774808399a38cd380177afe128ba38 100644 (file)
@@ -5,8 +5,9 @@
 // 
 // Authors
 //      Miguel de Icaza (miguel@novell.com)
+//     Sebastien Pouliot  <sebastien@ximian.com>
 //
-// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2007, 2008 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 // 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;
 
 namespace System.IO.IsolatedStorage {
 
+       // NOTES: 
+       // * Silverlight allows extending to more than AvailableFreeSpace (by up to 1024 bytes).
+       //   This looks like a safety buffer.
+
        public class IsolatedStorageFileStream : FileStream {
+
                IsolatedStorageFile container;
-                       
+
+               internal static string Verify (IsolatedStorageFile isf, string path)
+               {
+                       if (path == null)
+                               throw new ArgumentNullException ("path");
+                       if (path.Length == 0)
+                               throw new ArgumentException ("path");
+                       if (isf == null)
+                               throw new ArgumentNullException ("isf");
+
+                       isf.PreCheck ();
+                       return isf.Verify (path);
+               }
+
                public IsolatedStorageFileStream (string path, FileMode mode, IsolatedStorageFile isf)
-                       : base (IsolatedStorageFile.Verify (path), mode)
+                       : base (Verify (isf, path), mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), 
+                               FileShare.Read, DefaultBufferSize, false, true)
                {
                        container = isf;
                }
 
                public IsolatedStorageFileStream (string path, FileMode mode, FileAccess access, IsolatedStorageFile isf)
-                       : base (IsolatedStorageFile.Verify (path), mode, access)
+                       : base (Verify (isf, path), mode, access, FileShare.Read, DefaultBufferSize, false, true)
                {
                        container = isf;
                }
 
                public IsolatedStorageFileStream (string path, FileMode mode, FileAccess access, FileShare share, IsolatedStorageFile isf)
-                       : base (IsolatedStorageFile.Verify (path), mode, access, share)
+                       : base (Verify (isf, path), mode, access, share, DefaultBufferSize, false, true)
                {
                        container = isf;
                }
 
                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)
                {
+                       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)
                {
-                       WriteByte (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 bool IsAsync {
-                       get {
-                               return base.IsAsync;
-                       }
-               }
-
                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
\ No newline at end of file
+#endif