0d35d6c2f95a3a23c5ac6d9df5581a972b2060ae
[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 #if !MOONLIGHT
31 using System.Diagnostics;
32 using System.Globalization;
33 using System.Reflection;
34 using System.Security;
35 using System.Security.Permissions;
36 using System.Runtime.InteropServices;
37 using Microsoft.Win32.SafeHandles;
38
39 namespace System.IO.IsolatedStorage {
40
41         [ComVisible (true)]
42         public class IsolatedStorageFileStream : FileStream {
43
44                 [ReflectionPermission (SecurityAction.Assert, TypeInformation = true)]
45                 private static string CreateIsolatedPath (IsolatedStorageFile isf, string path, FileMode mode)
46                 {
47                         if (path == null)
48                                 throw new ArgumentNullException ("path");
49
50                         if (!Enum.IsDefined (typeof (FileMode), mode))
51                                 throw new ArgumentException ("mode");
52
53                         if (isf == null) {
54                                 // we can't call GetUserStoreForDomain here because it depends on 
55                                 // Assembly.GetCallingAssembly (), which would be our constructor,
56                                 // i.e. the result would always be mscorlib.dll. So we need to do 
57                                 // a small stack walk to find who's calling the constructor
58
59                                 StackFrame sf = new StackFrame (3); // skip self and constructor
60                                 isf = IsolatedStorageFile.GetStore (IsolatedStorageScope.User | IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly,
61 #if MOBILE
62                                         null, null);
63 #else
64                                         IsolatedStorageFile.GetDomainIdentityFromEvidence (AppDomain.CurrentDomain.Evidence), 
65                                         IsolatedStorageFile.GetAssemblyIdentityFromEvidence (sf.GetMethod ().ReflectedType.Assembly.UnprotectedGetEvidence ()));
66 #endif
67                         }
68
69 #if NET_4_0 || MOBILE
70                         if (isf.IsDisposed)
71                                 throw new ObjectDisposedException ("IsolatedStorageFile");
72                         if (isf.IsClosed)
73                                 throw new InvalidOperationException ("Storage needs to be open for this operation.");
74 #endif
75
76                         // ensure that the _root_ isolated storage can be (and is) created.
77                         FileInfo fi = new FileInfo (isf.Root);
78                         if (!fi.Directory.Exists)
79                                 fi.Directory.Create ();
80
81                         // remove the root path character(s) if they exist
82                         if (Path.IsPathRooted (path)) {
83                                 string root = Path.GetPathRoot (path);
84                                 path = path.Remove (0, root.Length);
85                         }
86
87                         // other directories (provided by 'path') must already exists
88                         string file = Path.Combine (isf.Root, path);
89
90                         string full = Path.GetFullPath (file);
91                         full = Path.GetFullPath (file);
92                         if (!full.StartsWith (isf.Root))
93                                 throw new IsolatedStorageException ();
94
95                         fi = new FileInfo (file);
96                         if (!fi.Directory.Exists) {
97                                 // don't leak the path information for isolated storage
98                                 string msg = Locale.GetText ("Could not find a part of the path \"{0}\".");
99                                 throw new DirectoryNotFoundException (String.Format (msg, path));
100                         }
101
102                         // FIXME: this is probably a good place to Assert our security
103                         // needs (once Mono supports imperative security stack modifiers)
104
105                         return file;
106                 }
107
108                 public IsolatedStorageFileStream (string path, FileMode mode)
109                         : this (path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.Read, DefaultBufferSize, null)
110                 {
111                 }       
112
113                 public IsolatedStorageFileStream (string path, FileMode mode, FileAccess access)
114                         : this (path, mode, access, access == FileAccess.Write ? FileShare.None : FileShare.Read, DefaultBufferSize, null)
115                 {
116                 }
117
118                 public IsolatedStorageFileStream (string path, FileMode mode, FileAccess access, FileShare share)
119                         : this (path, mode, access, share, DefaultBufferSize, null)
120                 {
121                 }
122
123                 public IsolatedStorageFileStream (string path, FileMode mode, FileAccess access, FileShare share, int bufferSize)
124                         : this (path, mode, access, share, bufferSize, null)
125                 {
126                 }
127
128                 // FIXME: Further limit the assertion when imperative Assert is implemented
129                 [FileIOPermission (SecurityAction.Assert, Unrestricted = true)]
130                 public IsolatedStorageFileStream (string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, IsolatedStorageFile isf)
131                         : base (CreateIsolatedPath (isf, path, mode), mode, access, share, bufferSize, false, true)
132                 {
133                 }
134
135                 public IsolatedStorageFileStream (string path, FileMode mode, FileAccess access, FileShare share, IsolatedStorageFile isf)
136                         : this (path, mode, access, share, DefaultBufferSize, isf)
137                 {
138                 }
139
140                 public IsolatedStorageFileStream (string path, FileMode mode, FileAccess access, IsolatedStorageFile isf)
141                         : this (path, mode, access, access == FileAccess.Write ? FileShare.None : FileShare.Read, DefaultBufferSize, isf)
142                 {
143                 }
144
145                 public IsolatedStorageFileStream (string path, FileMode mode, IsolatedStorageFile isf)
146                         : this (path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.Read, DefaultBufferSize, isf)
147                 {
148                 }
149
150                 public override bool CanRead {
151                         get {return base.CanRead;}
152                 }
153
154                 public override bool CanSeek {
155                         get {return base.CanSeek;}
156                 }
157
158                 public override bool CanWrite {
159                         get {return base.CanWrite;}
160                 }
161
162                 public override SafeFileHandle SafeFileHandle {
163                         [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
164                         get {
165                                 throw new IsolatedStorageException (
166                                         Locale.GetText ("Information is restricted"));
167                         }
168                 }
169
170                 [Obsolete ("Use SafeFileHandle - once available")]
171                 public override IntPtr Handle {
172                         [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
173                         get {
174                                 throw new IsolatedStorageException (
175                                         Locale.GetText ("Information is restricted"));
176                         }
177                 }
178
179                 public override bool IsAsync {
180                         get {return base.IsAsync;}
181                 }
182
183                 public override long Length {
184                         get {return base.Length;}
185                 }
186
187                 public override long Position {
188                         get {return base.Position;}
189                         set {base.Position = value;}
190                 }
191
192                 public override IAsyncResult BeginRead (byte[] buffer, int offset, int numBytes, AsyncCallback userCallback, object stateObject)
193                 {
194                         return base.BeginRead (buffer, offset, numBytes, userCallback, stateObject);
195                 }
196
197                 public override IAsyncResult BeginWrite (byte[] buffer, int offset, int numBytes, AsyncCallback userCallback, object stateObject)
198                 {
199                         return base.BeginWrite (buffer, offset, numBytes, userCallback, stateObject);
200                 }
201
202                 public override int EndRead (IAsyncResult asyncResult)
203                 {
204                         return base.EndRead (asyncResult);
205                 }
206
207                 public override void EndWrite (IAsyncResult asyncResult)
208                 {
209                         base.EndWrite (asyncResult);
210                 }
211
212                 public override void Flush ()
213                 {
214                         base.Flush ();
215                 }
216
217 #if NET_4_0 || MOBILE
218                 public override void Flush (bool flushToDisk)
219                 {
220                         base.Flush (flushToDisk);
221                 }
222 #endif
223
224                 public override int Read (byte[] buffer, int offset, int count)
225                 {
226                         return base.Read (buffer, offset, count);
227                 }
228
229                 public override int ReadByte ()
230                 {
231                         return base.ReadByte ();
232                 }
233
234                 public override long Seek (long offset, SeekOrigin origin)
235                 {
236                         return base.Seek (offset, origin);
237                 }
238
239                 public override void SetLength (long value)
240                 {
241                         base.SetLength (value);
242                 }
243
244                 public override void Write (byte[] buffer, int offset, int count)
245                 {
246                         base.Write (buffer, offset, count);
247                 }
248
249                 public override void WriteByte (byte value)
250                 {
251                         base.WriteByte (value);
252                 }
253
254                 protected override void Dispose (bool disposing)
255                 {
256                         base.Dispose (disposing);
257                 }
258         }
259 }
260 #endif