Merge pull request #1898 from alexanderkyte/debugger_variable_reflection
[mono.git] / mcs / class / corlib / System.IO.IsolatedStorage / IsolatedStorageFileStream.cs
1 //
2 // System.IO.IsolatedStorage.IsolatedStorageFileStream
3 //
4 // Authors
5 //      Sean MacIsaac (macisaac@ximian.com)
6 //      Sebastien Pouliot  <sebastien@ximian.com>
7 //
8 // (C) 2001 Ximian, Inc.
9 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 using System.Diagnostics;
31 using System.Globalization;
32 using System.Reflection;
33 using System.Security;
34 using System.Security.Permissions;
35 using System.Runtime.InteropServices;
36 using Microsoft.Win32.SafeHandles;
37
38 namespace System.IO.IsolatedStorage {
39
40         [ComVisible (true)]
41         public class IsolatedStorageFileStream : FileStream {
42
43                 [ReflectionPermission (SecurityAction.Assert, TypeInformation = true)]
44                 private static string CreateIsolatedPath (IsolatedStorageFile isf, string path, FileMode mode)
45                 {
46                         if (path == null)
47                                 throw new ArgumentNullException ("path");
48
49                         if (!Enum.IsDefined (typeof (FileMode), mode))
50                                 throw new ArgumentException ("mode");
51
52                         if (isf == null) {
53                                 // we can't call GetUserStoreForDomain here because it depends on 
54                                 // Assembly.GetCallingAssembly (), which would be our constructor,
55                                 // i.e. the result would always be mscorlib.dll. So we need to do 
56                                 // a small stack walk to find who's calling the constructor
57
58                                 isf = IsolatedStorageFile.GetStore (IsolatedStorageScope.User | IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly,
59 #if MOBILE
60                                         null, null);
61 #else
62                                         IsolatedStorageFile.GetDomainIdentityFromEvidence (AppDomain.CurrentDomain.Evidence), 
63                                         IsolatedStorageFile.GetAssemblyIdentityFromEvidence (new StackFrame (3).GetMethod ().ReflectedType.Assembly.UnprotectedGetEvidence ())); // skip self and constructor
64 #endif
65                         }
66
67                         if (isf.IsDisposed)
68                                 throw new ObjectDisposedException ("IsolatedStorageFile");
69                         if (isf.IsClosed)
70                                 throw new InvalidOperationException ("Storage needs to be open for this operation.");
71
72                         // ensure that the _root_ isolated storage can be (and is) created.
73                         FileInfo fi = new FileInfo (isf.Root);
74                         if (!fi.Directory.Exists)
75                                 fi.Directory.Create ();
76
77                         // remove the root path character(s) if they exist
78                         if (Path.IsPathRooted (path)) {
79                                 string root = Path.GetPathRoot (path);
80                                 path = path.Remove (0, root.Length);
81                         }
82
83                         // other directories (provided by 'path') must already exists
84                         string file = Path.Combine (isf.Root, path);
85
86                         string full = Path.GetFullPath (file);
87                         full = Path.GetFullPath (file);
88                         if (!full.StartsWith (isf.Root))
89                                 throw new IsolatedStorageException ();
90
91                         fi = new FileInfo (file);
92                         if (!fi.Directory.Exists) {
93                                 // don't leak the path information for isolated storage
94                                 string msg = Locale.GetText ("Could not find a part of the path \"{0}\".");
95                                 throw new DirectoryNotFoundException (String.Format (msg, path));
96                         }
97
98                         // FIXME: this is probably a good place to Assert our security
99                         // needs (once Mono supports imperative security stack modifiers)
100
101                         return file;
102                 }
103
104                 public IsolatedStorageFileStream (string path, FileMode mode)
105                         : this (path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.Read, DefaultBufferSize, null)
106                 {
107                 }       
108
109                 public IsolatedStorageFileStream (string path, FileMode mode, FileAccess access)
110                         : this (path, mode, access, access == FileAccess.Write ? FileShare.None : FileShare.Read, DefaultBufferSize, null)
111                 {
112                 }
113
114                 public IsolatedStorageFileStream (string path, FileMode mode, FileAccess access, FileShare share)
115                         : this (path, mode, access, share, DefaultBufferSize, null)
116                 {
117                 }
118
119                 public IsolatedStorageFileStream (string path, FileMode mode, FileAccess access, FileShare share, int bufferSize)
120                         : this (path, mode, access, share, bufferSize, null)
121                 {
122                 }
123
124                 // FIXME: Further limit the assertion when imperative Assert is implemented
125                 [FileIOPermission (SecurityAction.Assert, Unrestricted = true)]
126                 public IsolatedStorageFileStream (string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, IsolatedStorageFile isf)
127                         : base (CreateIsolatedPath (isf, path, mode), mode, access, share, bufferSize, false, true)
128                 {
129                 }
130
131                 public IsolatedStorageFileStream (string path, FileMode mode, FileAccess access, FileShare share, IsolatedStorageFile isf)
132                         : this (path, mode, access, share, DefaultBufferSize, isf)
133                 {
134                 }
135
136                 public IsolatedStorageFileStream (string path, FileMode mode, FileAccess access, IsolatedStorageFile isf)
137                         : this (path, mode, access, access == FileAccess.Write ? FileShare.None : FileShare.Read, DefaultBufferSize, isf)
138                 {
139                 }
140
141                 public IsolatedStorageFileStream (string path, FileMode mode, IsolatedStorageFile isf)
142                         : this (path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.Read, DefaultBufferSize, isf)
143                 {
144                 }
145
146                 public override bool CanRead {
147                         get {return base.CanRead;}
148                 }
149
150                 public override bool CanSeek {
151                         get {return base.CanSeek;}
152                 }
153
154                 public override bool CanWrite {
155                         get {return base.CanWrite;}
156                 }
157
158                 public override SafeFileHandle SafeFileHandle {
159                         [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
160                         get {
161                                 throw new IsolatedStorageException (
162                                         Locale.GetText ("Information is restricted"));
163                         }
164                 }
165
166                 [Obsolete ("Use SafeFileHandle - once available")]
167                 public override IntPtr Handle {
168                         [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
169                         get {
170                                 throw new IsolatedStorageException (
171                                         Locale.GetText ("Information is restricted"));
172                         }
173                 }
174
175                 public override bool IsAsync {
176                         get {return base.IsAsync;}
177                 }
178
179                 public override long Length {
180                         get {return base.Length;}
181                 }
182
183                 public override long Position {
184                         get {return base.Position;}
185                         set {base.Position = value;}
186                 }
187
188                 public override IAsyncResult BeginRead (byte[] buffer, int offset, int numBytes, AsyncCallback userCallback, object stateObject)
189                 {
190                         return base.BeginRead (buffer, offset, numBytes, userCallback, stateObject);
191                 }
192
193                 public override IAsyncResult BeginWrite (byte[] buffer, int offset, int numBytes, AsyncCallback userCallback, object stateObject)
194                 {
195                         return base.BeginWrite (buffer, offset, numBytes, userCallback, stateObject);
196                 }
197
198                 public override int EndRead (IAsyncResult asyncResult)
199                 {
200                         return base.EndRead (asyncResult);
201                 }
202
203                 public override void EndWrite (IAsyncResult asyncResult)
204                 {
205                         base.EndWrite (asyncResult);
206                 }
207
208                 public override void Flush ()
209                 {
210                         base.Flush ();
211                 }
212
213                 public override void Flush (bool flushToDisk)
214                 {
215                         base.Flush (flushToDisk);
216                 }
217
218                 public override int Read (byte[] buffer, int offset, int count)
219                 {
220                         return base.Read (buffer, offset, count);
221                 }
222
223                 public override int ReadByte ()
224                 {
225                         return base.ReadByte ();
226                 }
227
228                 public override long Seek (long offset, SeekOrigin origin)
229                 {
230                         return base.Seek (offset, origin);
231                 }
232
233                 public override void SetLength (long value)
234                 {
235                         base.SetLength (value);
236                 }
237
238                 public override void Write (byte[] buffer, int offset, int count)
239                 {
240                         base.Write (buffer, offset, count);
241                 }
242
243                 public override void WriteByte (byte value)
244                 {
245                         base.WriteByte (value);
246                 }
247
248                 protected override void Dispose (bool disposing)
249                 {
250                         base.Dispose (disposing);
251                 }
252         }
253 }