Merge pull request #856 from madewokherd/textcontrol
[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 NET_4_0
68                         if (isf.IsDisposed)
69                                 throw new ObjectDisposedException ("IsolatedStorageFile");
70                         if (isf.IsClosed)
71                                 throw new InvalidOperationException ("Storage needs to be open for this operation.");
72 #endif
73
74                         // ensure that the _root_ isolated storage can be (and is) created.
75                         FileInfo fi = new FileInfo (isf.Root);
76                         if (!fi.Directory.Exists)
77                                 fi.Directory.Create ();
78
79                         // remove the root path character(s) if they exist
80                         if (Path.IsPathRooted (path)) {
81                                 string root = Path.GetPathRoot (path);
82                                 path = path.Remove (0, root.Length);
83                         }
84
85                         // other directories (provided by 'path') must already exists
86                         string file = Path.Combine (isf.Root, path);
87
88                         string full = Path.GetFullPath (file);
89                         full = Path.GetFullPath (file);
90                         if (!full.StartsWith (isf.Root))
91                                 throw new IsolatedStorageException ();
92
93                         fi = new FileInfo (file);
94                         if (!fi.Directory.Exists) {
95                                 // don't leak the path information for isolated storage
96                                 string msg = Locale.GetText ("Could not find a part of the path \"{0}\".");
97                                 throw new DirectoryNotFoundException (String.Format (msg, path));
98                         }
99
100                         // FIXME: this is probably a good place to Assert our security
101                         // needs (once Mono supports imperative security stack modifiers)
102
103                         return file;
104                 }
105
106                 public IsolatedStorageFileStream (string path, FileMode mode)
107                         : this (path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.Read, DefaultBufferSize, null)
108                 {
109                 }       
110
111                 public IsolatedStorageFileStream (string path, FileMode mode, FileAccess access)
112                         : this (path, mode, access, access == FileAccess.Write ? FileShare.None : FileShare.Read, DefaultBufferSize, null)
113                 {
114                 }
115
116                 public IsolatedStorageFileStream (string path, FileMode mode, FileAccess access, FileShare share)
117                         : this (path, mode, access, share, DefaultBufferSize, null)
118                 {
119                 }
120
121                 public IsolatedStorageFileStream (string path, FileMode mode, FileAccess access, FileShare share, int bufferSize)
122                         : this (path, mode, access, share, bufferSize, null)
123                 {
124                 }
125
126                 // FIXME: Further limit the assertion when imperative Assert is implemented
127                 [FileIOPermission (SecurityAction.Assert, Unrestricted = true)]
128                 public IsolatedStorageFileStream (string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, IsolatedStorageFile isf)
129                         : base (CreateIsolatedPath (isf, path, mode), mode, access, share, bufferSize, false, true)
130                 {
131                 }
132
133                 public IsolatedStorageFileStream (string path, FileMode mode, FileAccess access, FileShare share, IsolatedStorageFile isf)
134                         : this (path, mode, access, share, DefaultBufferSize, isf)
135                 {
136                 }
137
138                 public IsolatedStorageFileStream (string path, FileMode mode, FileAccess access, IsolatedStorageFile isf)
139                         : this (path, mode, access, access == FileAccess.Write ? FileShare.None : FileShare.Read, DefaultBufferSize, isf)
140                 {
141                 }
142
143                 public IsolatedStorageFileStream (string path, FileMode mode, IsolatedStorageFile isf)
144                         : this (path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.Read, DefaultBufferSize, isf)
145                 {
146                 }
147
148                 public override bool CanRead {
149                         get {return base.CanRead;}
150                 }
151
152                 public override bool CanSeek {
153                         get {return base.CanSeek;}
154                 }
155
156                 public override bool CanWrite {
157                         get {return base.CanWrite;}
158                 }
159
160                 public override SafeFileHandle SafeFileHandle {
161                         [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
162                         get {
163                                 throw new IsolatedStorageException (
164                                         Locale.GetText ("Information is restricted"));
165                         }
166                 }
167
168                 [Obsolete ("Use SafeFileHandle - once available")]
169                 public override IntPtr Handle {
170                         [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
171                         get {
172                                 throw new IsolatedStorageException (
173                                         Locale.GetText ("Information is restricted"));
174                         }
175                 }
176
177                 public override bool IsAsync {
178                         get {return base.IsAsync;}
179                 }
180
181                 public override long Length {
182                         get {return base.Length;}
183                 }
184
185                 public override long Position {
186                         get {return base.Position;}
187                         set {base.Position = value;}
188                 }
189
190                 public override IAsyncResult BeginRead (byte[] buffer, int offset, int numBytes, AsyncCallback userCallback, object stateObject)
191                 {
192                         return base.BeginRead (buffer, offset, numBytes, userCallback, stateObject);
193                 }
194
195                 public override IAsyncResult BeginWrite (byte[] buffer, int offset, int numBytes, AsyncCallback userCallback, object stateObject)
196                 {
197                         return base.BeginWrite (buffer, offset, numBytes, userCallback, stateObject);
198                 }
199
200                 public override int EndRead (IAsyncResult asyncResult)
201                 {
202                         return base.EndRead (asyncResult);
203                 }
204
205                 public override void EndWrite (IAsyncResult asyncResult)
206                 {
207                         base.EndWrite (asyncResult);
208                 }
209
210                 public override void Flush ()
211                 {
212                         base.Flush ();
213                 }
214
215 #if NET_4_0
216                 public override void Flush (bool flushToDisk)
217                 {
218                         base.Flush (flushToDisk);
219                 }
220 #endif
221
222                 public override int Read (byte[] buffer, int offset, int count)
223                 {
224                         return base.Read (buffer, offset, count);
225                 }
226
227                 public override int ReadByte ()
228                 {
229                         return base.ReadByte ();
230                 }
231
232                 public override long Seek (long offset, SeekOrigin origin)
233                 {
234                         return base.Seek (offset, origin);
235                 }
236
237                 public override void SetLength (long value)
238                 {
239                         base.SetLength (value);
240                 }
241
242                 public override void Write (byte[] buffer, int offset, int count)
243                 {
244                         base.Write (buffer, offset, count);
245                 }
246
247                 public override void WriteByte (byte value)
248                 {
249                         base.WriteByte (value);
250                 }
251
252                 protected override void Dispose (bool disposing)
253                 {
254                         base.Dispose (disposing);
255                 }
256         }
257 }