Add unit test for AggregateException.GetBaseException that works on .net but is broke...
[mono.git] / mcs / class / System.Core / System.IO.MemoryMappedFiles / MemoryMappedFile.cs
1 //
2 // MemoryMappedFile.cs
3 //
4 // Authors:
5 //      Zoltan Varga (vargaz@gmail.com)
6 //
7 // Copyright (C) 2009, Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 #if NET_4_0
30
31 using System;
32 using System.IO;
33 using System.Collections.Generic;
34 using Microsoft.Win32.SafeHandles;
35 using System.Runtime.InteropServices;
36
37
38 #if !MOBILE
39 using Mono.Unix.Native;
40 using Mono.Unix;
41 #else
42 using System.Runtime.CompilerServices;
43 #endif
44
45 namespace System.IO.MemoryMappedFiles
46 {
47 #if !MOBILE
48         internal static class MemoryMapImpl {
49                 //
50                 // Turns the FileMode into the first half of open(2) flags
51                 //
52                 static OpenFlags ToUnixMode (FileMode mode)
53                 {
54                         switch (mode){
55                         case FileMode.CreateNew:
56                                 return OpenFlags.O_CREAT | OpenFlags.O_EXCL;
57                                 
58                         case FileMode.Create:
59                                 return OpenFlags.O_CREAT | OpenFlags.O_TRUNC;
60                                 
61                         case FileMode.OpenOrCreate:
62                                 return OpenFlags.O_CREAT;
63                                 
64                         case FileMode.Truncate:
65                                 return OpenFlags.O_TRUNC;
66                                 
67                         case FileMode.Append:
68                                 return OpenFlags.O_APPEND;
69                         default:
70                         case FileMode.Open:
71                                 return 0;
72                         }
73                 }
74
75                 //
76                 // Turns the MemoryMappedFileAccess into the second half of open(2) flags
77                 //
78                 static OpenFlags ToUnixMode (MemoryMappedFileAccess access)
79                 {
80                         switch (access){
81                         case MemoryMappedFileAccess.CopyOnWrite:
82                         case MemoryMappedFileAccess.ReadWriteExecute:
83                         case MemoryMappedFileAccess.ReadWrite:
84                                 return OpenFlags.O_RDWR;
85                                 
86                         case MemoryMappedFileAccess.Write:
87                                 return OpenFlags.O_WRONLY;
88
89                         case MemoryMappedFileAccess.ReadExecute:
90                         case MemoryMappedFileAccess.Read:
91                         default:
92                                 return OpenFlags.O_RDONLY;
93                         }
94                 }
95
96                 static MmapProts ToUnixProts (MemoryMappedFileAccess access)
97                 {
98                         switch (access){
99                         case MemoryMappedFileAccess.ReadWrite:
100                                 return MmapProts.PROT_WRITE | MmapProts.PROT_READ;
101                                 
102                         case MemoryMappedFileAccess.Write:
103                                 return MmapProts.PROT_WRITE;
104                                 
105                         case MemoryMappedFileAccess.CopyOnWrite:
106                                 return MmapProts.PROT_WRITE | MmapProts.PROT_READ;
107                                 
108                         case MemoryMappedFileAccess.ReadExecute:
109                                 return MmapProts.PROT_EXEC;
110                                 
111                         case MemoryMappedFileAccess.ReadWriteExecute:
112                                 return MmapProts.PROT_WRITE | MmapProts.PROT_READ | MmapProts.PROT_EXEC;
113                                 
114                         case MemoryMappedFileAccess.Read:
115                         default:
116                                 return MmapProts.PROT_READ;
117                         }
118                 }
119
120                 internal static int Open (string path, FileMode mode, long capacity, MemoryMappedFileAccess access)
121                 {
122                         if (MonoUtil.IsUnix){
123                                 Stat buf;
124                                 if (Syscall.stat (path, out buf) == -1)
125                                         UnixMarshal.ThrowExceptionForLastError ();
126
127                                 if ((capacity == 0 && buf.st_size == 0) || (capacity > buf.st_size))
128                                         throw new ArgumentException ("capacity");
129
130                                 int fd = Syscall.open (path, ToUnixMode (mode) | ToUnixMode (access), FilePermissions.DEFFILEMODE);
131
132                                 if (fd == -1)
133                                         UnixMarshal.ThrowExceptionForLastError ();
134                                 return fd;
135                         } else
136                                 throw new NotImplementedException ();
137                 }
138                 
139                 internal static void CloseFD (int fd) {
140                         Syscall.close (fd);
141                 }
142
143                 internal static void Flush (int fd) {
144                         if (MonoUtil.IsUnix)
145                                 Syscall.fsync (fd);
146                         else
147                                 throw new NotImplementedException ("Not implemented on Windows");
148                         
149                 }
150
151                 static int pagesize;
152
153                 internal static unsafe void Map (int file_handle, long offset, ref long size, MemoryMappedFileAccess access, out IntPtr map_addr, out int offset_diff)
154                 {
155                         if (!MonoUtil.IsUnix)
156                                 throw new NotImplementedException ("Not implemented on windows.");
157
158                         if (pagesize == 0)
159                                 pagesize = Syscall.getpagesize ();
160
161                         Stat buf;
162                         Syscall.fstat (file_handle, out buf);
163                         long fsize = buf.st_size;
164
165                         if (size == 0 || size > fsize)
166                                 size = fsize;
167                         
168                         // Align offset
169                         long real_offset = offset & ~(pagesize - 1);
170
171                         offset_diff = (int)(offset - real_offset);
172
173                         // FIXME: Need to determine the unix fd for the file, Handle is only
174                         // equal to it by accident
175                         //
176                         // The new API no longer uses FileStream everywhere, but exposes instead
177                         // the filename (with one exception), we could move this API to use
178                         // file descriptors instead of the FileStream plus its Handle.
179                         //
180                         map_addr = Syscall.mmap (IntPtr.Zero, (ulong) size,
181                                                  ToUnixProts (access),
182                                                  access == MemoryMappedFileAccess.CopyOnWrite ? MmapFlags.MAP_PRIVATE : MmapFlags.MAP_SHARED,
183                                                  file_handle, real_offset);
184
185                         if (map_addr == (IntPtr)(-1))
186                                 throw new IOException ("mmap failed for fd#" + file_handle + "(" + offset + ", " + size + ")");
187                 }
188
189                 internal static bool Unmap (IntPtr map_addr, ulong map_size)
190                 {
191                         if (!MonoUtil.IsUnix)
192                                 return false;
193                         return Syscall.munmap (map_addr, map_size) == 0;
194                 }
195
196                 static void ConfigureUnixFD (IntPtr handle, HandleInheritability h)
197                 {
198                         // TODO: Mono.Posix is lacking O_CLOEXEC definitions for fcntl.
199                 }
200
201
202                 [DllImport("kernel32", SetLastError = true)]
203                 static extern bool SetHandleInformation (IntPtr hObject, int dwMask, int dwFlags);
204                 static void ConfigureWindowsFD (IntPtr handle, HandleInheritability h)
205                 {
206                         SetHandleInformation (handle, 1 /* FLAG_INHERIT */, h == HandleInheritability.None ? 0 : 1);
207                 }
208                 
209                 internal static void ConfigureFD (IntPtr handle, HandleInheritability inheritability)
210                 {
211                         if (MonoUtil.IsUnix)
212                                 ConfigureUnixFD (handle, inheritability);
213                         else
214                                 ConfigureWindowsFD (handle, inheritability);
215                 }
216
217         }
218 #else
219         internal static class MemoryMapImpl {
220                 [DllImport ("libc")]
221                 static extern int fsync (int fd);
222
223                 [DllImport ("libc")]
224                 static extern int close (int fd);
225
226                 [DllImport ("libc")]
227                 static extern int fcntl (int fd, int cmd, int arg0);
228
229                 //XXX check if android off_t is 64bits or not. on iOS / darwin it is.
230                 [DllImport ("libc")]
231                 static extern IntPtr mmap (IntPtr addr, IntPtr len, int prot, int flags, int fd, long offset);
232
233                 [DllImport ("libc")]
234                 static extern int munmap (IntPtr addr, IntPtr size);
235
236                 [DllImport ("libc", SetLastError=true)]
237                 static extern int open (string path, int flags, int access);
238
239 #if MONODROID
240                 [DllImport ("__Internal")]
241                 static extern int monodroid_getpagesize ();
242
243                 static int getpagesize ()
244                 {
245                         return monodroid_getpagesize ();
246                 }
247 #else
248                 [DllImport ("libc")]
249                 static extern int getpagesize ();
250 #endif
251
252                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
253                 static extern long mono_filesize_from_path (string str);
254
255                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
256                 static extern long mono_filesize_from_fd (int fd);
257
258                 //Values valid on iOS/OSX and android ndk r6
259                 const int F_GETFD = 1;
260                 const int F_SETFD = 2;
261                 const int FD_CLOEXEC = 1;
262                 const int DEFFILEMODE = 0x666;
263
264                 const int O_RDONLY = 0x0;
265                 const int O_WRONLY = 0x1;
266                 const int O_RDWR   = 0x2;
267
268                 const int PROT_READ  = 0x1;
269                 const int PROT_WRITE = 0x2;
270                 const int PROT_EXEC  = 0x4;
271
272                 const int MAP_PRIVATE = 0x2;
273                 const int MAP_SHARED  = 0x1;
274
275                 const int EINVAL = 22;
276
277 #if MONODROID
278                 const int O_CREAT = 0x040;
279                 const int O_TRUNC = 0x080;
280                 const int O_EXCL  = 0x200;
281
282                 const int ENAMETOOLONG = 63;
283 #else
284                 /* MONOTOUCH */
285                 const int O_CREAT = 0x0200;
286                 const int O_TRUNC = 0x0400;
287                 const int O_EXCL  = 0x0800;
288
289                 const int ENAMETOOLONG = 36;
290 #endif
291
292                 static int ToUnixMode (FileMode mode)
293                 {
294                         switch (mode) {
295                         case FileMode.CreateNew:
296                                 return O_CREAT | O_EXCL;
297                                 
298                         case FileMode.Create:
299                                 return O_CREAT | O_TRUNC;
300                                 
301                         case FileMode.OpenOrCreate:
302                                 return O_CREAT;
303                                 
304                         case FileMode.Truncate:
305                                 return O_TRUNC;
306                         default:
307                         case FileMode.Open:
308                                 return 0;
309                         }
310                 }
311
312                 //
313                 // Turns the MemoryMappedFileAccess into the second half of open(2) flags
314                 //
315                 static int ToUnixMode (MemoryMappedFileAccess access)
316                 {
317                         switch (access) {
318                         case MemoryMappedFileAccess.CopyOnWrite:
319                         case MemoryMappedFileAccess.ReadWriteExecute:
320                         case MemoryMappedFileAccess.ReadWrite:
321                                 return O_RDWR;
322                                 
323                         case MemoryMappedFileAccess.Write:
324                                 return O_WRONLY;
325
326                         case MemoryMappedFileAccess.ReadExecute:
327                         case MemoryMappedFileAccess.Read:
328                         default:
329                                 return O_RDONLY;
330                         }
331                 }
332
333                 static int ToUnixProts (MemoryMappedFileAccess access)
334                 {
335                         switch (access){
336                         case MemoryMappedFileAccess.ReadWrite:
337                                 return PROT_WRITE | PROT_READ;
338                                 
339                         case MemoryMappedFileAccess.Write:
340                                 return PROT_WRITE;
341                                 
342                         case MemoryMappedFileAccess.CopyOnWrite:
343                                 return PROT_WRITE | PROT_READ;
344                                 
345                         case MemoryMappedFileAccess.ReadExecute:
346                                 return PROT_EXEC;
347                                 
348                         case MemoryMappedFileAccess.ReadWriteExecute:
349                                 return PROT_WRITE | PROT_READ | PROT_EXEC;
350                                 
351                         case MemoryMappedFileAccess.Read:
352                         default:
353                                 return PROT_READ;
354                         }
355                 }
356
357                 static void ThrowErrorFromErrno (int errno) 
358                 {
359                         switch (errno) {
360                         case EINVAL:            throw new ArgumentException ();
361                         case ENAMETOOLONG:      throw new PathTooLongException ();
362                         default: throw new IOException ("Failed with errno " + errno);
363                         }
364                 }
365
366                 internal static int Open (string path, FileMode mode, long capacity, MemoryMappedFileAccess access)
367                 {
368                         long file_size = mono_filesize_from_path (path);
369                         if (file_size < 0)
370                                 throw new FileNotFoundException (path);
371
372                         if ((capacity == 0 && file_size == 0) || (capacity > file_size))
373                                 throw new ArgumentException ("capacity");
374
375                         int fd = open (path, ToUnixMode (mode) | ToUnixMode (access), DEFFILEMODE);
376
377                         if (fd == -1)
378                                 ThrowErrorFromErrno (Marshal.GetLastWin32Error ());
379                         return fd;
380                 }
381
382                 internal static void CloseFD (int fd)
383                 {
384                         close (fd);
385                 }
386
387                 internal static void Flush (int fd)
388                 {
389                         fsync (fd);
390                 }
391
392                 internal static bool Unmap (IntPtr map_addr, ulong map_size)
393                 {
394                         return munmap (map_addr, (IntPtr)map_size) == 0;
395                 }
396
397                 static int pagesize;
398
399                 internal static unsafe void Map (int file_handle, long offset, ref long size, MemoryMappedFileAccess access, out IntPtr map_addr, out int offset_diff)
400                 {
401                         if (pagesize == 0)
402                                 pagesize = getpagesize ();
403
404                         long fsize = mono_filesize_from_fd (file_handle);
405                         if (fsize < 0)
406                                 throw new FileNotFoundException ();
407
408                         if (size == 0 || size > fsize)
409                                 size = fsize;
410                         
411                         // Align offset
412                         long real_offset = offset & ~(pagesize - 1);
413
414                         offset_diff = (int)(offset - real_offset);
415
416                         map_addr = mmap (IntPtr.Zero, (IntPtr) size,
417                                                  ToUnixProts (access),
418                                                  access == MemoryMappedFileAccess.CopyOnWrite ? MAP_PRIVATE : MAP_SHARED,
419                                                  file_handle, real_offset);
420
421                         if (map_addr == (IntPtr)(-1))
422                                 throw new IOException ("mmap failed for fd#" + file_handle + "(" + offset + ", " + size + ")");
423                 }
424
425                 internal static void ConfigureFD (IntPtr handle, HandleInheritability inheritability)
426                 {
427                         int fd = (int)handle;
428                         int flags = fcntl (fd, F_GETFD, 0);
429                         if (inheritability == HandleInheritability.None)
430                                 flags &= ~FD_CLOEXEC;
431                         else
432                                 flags |= FD_CLOEXEC;
433                         fcntl (fd, F_SETFD, flags);
434                 }
435
436         }
437 #endif
438
439         public class MemoryMappedFile : IDisposable {
440                 MemoryMappedFileAccess fileAccess;
441                 string name;
442                 long fileCapacity;
443
444                 //
445                 // We allow the use of either the FileStream/keepOpen combo
446                 // or a Unix file descriptor.  This way we avoid the dependency on
447                 // Mono's io-layer having the Unix file descriptors mapped to
448                 // the same io-layer handle
449                 //
450                 FileStream stream;
451                 bool keepOpen;
452                 int unix_fd;
453
454                 public static MemoryMappedFile CreateFromFile (string path)
455                 {
456                         return CreateFromFile (path, FileMode.Open, null, 0, MemoryMappedFileAccess.ReadWrite);
457                 }
458
459                 public static MemoryMappedFile CreateFromFile (string path, FileMode mode)
460                 {
461                         return CreateFromFile (path, mode, null, 0, MemoryMappedFileAccess.ReadWrite);
462                 }
463
464                 public static MemoryMappedFile CreateFromFile (string path, FileMode mode, string mapName)
465                 {
466                         return CreateFromFile (path, mode, mapName, 0, MemoryMappedFileAccess.ReadWrite);
467                 }
468
469                 public static MemoryMappedFile CreateFromFile (string path, FileMode mode, string mapName, long capacity)
470                 {
471                         return CreateFromFile (path, mode, mapName, capacity, MemoryMappedFileAccess.ReadWrite);
472                 }
473
474                 public static MemoryMappedFile CreateFromFile (string path, FileMode mode, string mapName, long capacity, MemoryMappedFileAccess access)
475                 {
476                         if (path == null)
477                                 throw new ArgumentNullException ("path");
478                         if (path.Length == 0)
479                                 throw new ArgumentException ("path");
480                         if (mapName != null && mapName.Length == 0)
481                                 throw new ArgumentException ("mapName");
482                         if (mode == FileMode.Append)
483                                 throw new ArgumentException ("mode");                   
484
485                         int fd = MemoryMapImpl.Open (path, mode, capacity, access);
486                         
487                         return new MemoryMappedFile () {
488                                 unix_fd = fd,
489                                 fileAccess = access,
490                                 name = mapName,
491                                 fileCapacity = capacity
492                         };
493                 }
494
495 #if MOBILE
496                 public static MemoryMappedFile CreateFromFile (FileStream fileStream, string mapName, long capacity, MemoryMappedFileAccess access,
497                                                                HandleInheritability inheritability,
498                                                                bool leaveOpen)
499 #else
500                 [MonoLimitation ("memoryMappedFileSecurity is currently ignored")]
501                 public static MemoryMappedFile CreateFromFile (FileStream fileStream, string mapName, long capacity, MemoryMappedFileAccess access,
502                                                                MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability inheritability,
503                                                                bool leaveOpen)
504 #endif
505                 {
506                         if (fileStream == null)
507                                 throw new ArgumentNullException ("fileStream");
508                         if (mapName != null && mapName.Length == 0)
509                                 throw new ArgumentException ("mapName");
510                         if ((capacity == 0 && fileStream.Length == 0) || (capacity > fileStream.Length))
511                                 throw new ArgumentException ("capacity");
512
513                         MemoryMapImpl.ConfigureFD (fileStream.Handle, inheritability);
514                                 
515                         return new MemoryMappedFile () {
516                                 stream = fileStream,
517                                 fileAccess = access,
518                                 name = mapName,
519                                 fileCapacity = capacity,
520                                 keepOpen = leaveOpen
521                         };
522                 }
523
524                 [MonoLimitation ("CreateNew requires that mapName be a file name on Unix")]
525                 public static MemoryMappedFile CreateNew (string mapName, long capacity)
526                 {
527 #if MOBILE
528                         return CreateNew (mapName, capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.DelayAllocatePages, 0);
529 #else
530                         return CreateNew (mapName, capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.DelayAllocatePages, null, 0);
531 #endif
532                 }
533
534                 [MonoLimitation ("CreateNew requires that mapName be a file name on Unix")]
535                 public static MemoryMappedFile CreateNew (string mapName, long capacity, MemoryMappedFileAccess access) 
536                 {
537 #if MOBILE
538                         return CreateNew (mapName, capacity, access, MemoryMappedFileOptions.DelayAllocatePages, 0);
539 #else
540                         return CreateNew (mapName, capacity, access, MemoryMappedFileOptions.DelayAllocatePages, null, 0);
541 #endif
542                 }
543
544 #if MOBILE
545                 public static MemoryMappedFile CreateNew (string mapName, long capacity, MemoryMappedFileAccess access,
546                                                           MemoryMappedFileOptions options, 
547                                                           HandleInheritability handleInheritability)
548 #else
549                 [MonoLimitation ("CreateNew requires that mapName be a file name on Unix; options and memoryMappedFileSecurity are ignored")]
550                 public static MemoryMappedFile CreateNew (string mapName, long capacity, MemoryMappedFileAccess access,
551                                                           MemoryMappedFileOptions options, MemoryMappedFileSecurity memoryMappedFileSecurity,
552                                                           HandleInheritability inheritability)
553 #endif
554                 {
555                         return CreateFromFile (mapName, FileMode.CreateNew, mapName, capacity, access);
556                 }
557
558                 [MonoLimitation ("CreateOrOpen requires that mapName be a file name on Unix")]
559                 public static MemoryMappedFile CreateOrOpen (string mapName, long capacity)
560                 {
561                         return CreateOrOpen (mapName, capacity, MemoryMappedFileAccess.ReadWrite);
562                 }
563
564                 [MonoLimitation ("CreateOrOpen requires that mapName be a file name on Unix")]
565                 public static MemoryMappedFile CreateOrOpen (string mapName, long capacity, MemoryMappedFileAccess access)
566                 {
567                         return CreateFromFile (mapName, FileMode.OpenOrCreate, mapName, capacity, access); 
568                 }
569
570                 [MonoTODO]
571 #if MOBILE
572                 public static MemoryMappedFile CreateOrOpen (string mapName, long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, HandleInheritability inheritability)
573 #else
574                 public static MemoryMappedFile CreateOrOpen (string mapName, long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability inheritability)
575 #endif
576                 {
577                         throw new NotImplementedException ();
578                 }
579
580                 [MonoTODO]
581                 public static MemoryMappedFile OpenExisting (string mapName)
582                 {
583                         throw new NotImplementedException ();
584                 }
585
586                 [MonoTODO]
587                 public static MemoryMappedFile OpenExisting (string mapName, MemoryMappedFileRights desiredAccessRights)
588                 {
589                         throw new NotImplementedException ();
590                 }
591
592                 [MonoTODO]
593                 public static MemoryMappedFile OpenExisting (string mapName, MemoryMappedFileRights desiredAccessRights, HandleInheritability inheritability)
594                 {
595                         throw new NotImplementedException ();
596                 }
597
598                 public MemoryMappedViewStream CreateViewStream ()
599                 {
600                         return CreateViewStream (0, 0);
601                 }
602
603                 public MemoryMappedViewStream CreateViewStream (long offset, long size)
604                 {
605                         return CreateViewStream (offset, size, MemoryMappedFileAccess.ReadWrite);
606                 }
607
608                 public MemoryMappedViewStream CreateViewStream (long offset, long size, MemoryMappedFileAccess access)
609                 {
610                         return new MemoryMappedViewStream (stream != null ? (int)stream.Handle : unix_fd, offset, size, access);
611                 }
612
613                 public MemoryMappedViewAccessor CreateViewAccessor ()
614                 {
615                         return CreateViewAccessor (0, 0);
616                 }
617
618                 public MemoryMappedViewAccessor CreateViewAccessor (long offset, long size)
619                 {
620                         return CreateViewAccessor (offset, size, MemoryMappedFileAccess.ReadWrite);
621                 }
622
623                 public MemoryMappedViewAccessor CreateViewAccessor (long offset, long size, MemoryMappedFileAccess access)
624                 {
625                         int file_handle = stream != null ? (int) stream.Handle : unix_fd;
626                         
627                         return new MemoryMappedViewAccessor (file_handle, offset, size, access);
628                 }
629
630                 MemoryMappedFile ()
631                 {
632                 }
633
634                 public void Dispose ()
635                 {
636                         Dispose (true);
637                 }
638
639                 protected virtual void Dispose (bool disposing)
640                 {
641                         if (disposing){
642                                 if (stream != null){
643                                         if (keepOpen == false)
644                                                 stream.Close ();
645                                         unix_fd = -1;
646                                         stream = null;
647                                 }
648                                 if (unix_fd != -1) {
649                                         MemoryMapImpl.CloseFD (unix_fd);
650                                         unix_fd = -1;
651                                 }
652                         }
653                 }
654
655 #if !MOBILE
656                 [MonoTODO]
657                 public MemoryMappedFileSecurity GetAccessControl ()
658                 {
659                         throw new NotImplementedException ();
660                 }
661
662                 [MonoTODO]
663                 public void SetAccessControl (MemoryMappedFileSecurity memoryMappedFileSecurity)
664                 {
665                         throw new NotImplementedException ();
666                 }
667 #endif
668
669                 [MonoTODO]
670                 public SafeMemoryMappedFileHandle SafeMemoryMappedFileHandle {
671                         get {
672                                 throw new NotImplementedException ();
673                         }
674                 }
675         }
676 }
677
678 #endif