Merge pull request #498 from Unroll-Me/master
[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 || MOBILE
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                 [DllImport ("libc")]
240                 static extern int getpagesize ();
241
242                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
243                 static extern long mono_filesize_from_path (string str);
244
245                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
246                 static extern long mono_filesize_from_fd (int fd);
247
248                 //Values valid on iOS/OSX and android ndk r6
249                 const int F_GETFD = 1;
250                 const int F_SETFD = 2;
251                 const int FD_CLOEXEC = 1;
252                 const int DEFFILEMODE = 0x666;
253
254                 const int O_RDONLY = 0x0;
255                 const int O_WRONLY = 0x1;
256                 const int O_RDWR   = 0x2;
257
258                 const int PROT_READ  = 0x1;
259                 const int PROT_WRITE = 0x2;
260                 const int PROT_EXEC  = 0x4;
261
262                 const int MAP_PRIVATE = 0x2;
263                 const int MAP_SHARED  = 0x1;
264
265                 const int EINVAL = 22;
266
267 #if MONODROID
268                 const int O_CREAT = 0x040;
269                 const int O_TRUNC = 0x080;
270                 const int O_EXCL  = 0x200;
271
272                 const int ENAMETOOLONG = 63;
273 #else
274                 /* MONOTOUCH */
275                 const int O_CREAT = 0x0200;
276                 const int O_TRUNC = 0x0400;
277                 const int O_EXCL  = 0x0800;
278
279                 const int ENAMETOOLONG = 36;
280 #endif
281
282                 static int ToUnixMode (FileMode mode)
283                 {
284                         switch (mode) {
285                         case FileMode.CreateNew:
286                                 return O_CREAT | O_EXCL;
287                                 
288                         case FileMode.Create:
289                                 return O_CREAT | O_TRUNC;
290                                 
291                         case FileMode.OpenOrCreate:
292                                 return O_CREAT;
293                                 
294                         case FileMode.Truncate:
295                                 return O_TRUNC;
296                         default:
297                         case FileMode.Open:
298                                 return 0;
299                         }
300                 }
301
302                 //
303                 // Turns the MemoryMappedFileAccess into the second half of open(2) flags
304                 //
305                 static int ToUnixMode (MemoryMappedFileAccess access)
306                 {
307                         switch (access) {
308                         case MemoryMappedFileAccess.CopyOnWrite:
309                         case MemoryMappedFileAccess.ReadWriteExecute:
310                         case MemoryMappedFileAccess.ReadWrite:
311                                 return O_RDWR;
312                                 
313                         case MemoryMappedFileAccess.Write:
314                                 return O_WRONLY;
315
316                         case MemoryMappedFileAccess.ReadExecute:
317                         case MemoryMappedFileAccess.Read:
318                         default:
319                                 return O_RDONLY;
320                         }
321                 }
322
323                 static int ToUnixProts (MemoryMappedFileAccess access)
324                 {
325                         switch (access){
326                         case MemoryMappedFileAccess.ReadWrite:
327                                 return PROT_WRITE | PROT_READ;
328                                 
329                         case MemoryMappedFileAccess.Write:
330                                 return PROT_WRITE;
331                                 
332                         case MemoryMappedFileAccess.CopyOnWrite:
333                                 return PROT_WRITE | PROT_READ;
334                                 
335                         case MemoryMappedFileAccess.ReadExecute:
336                                 return PROT_EXEC;
337                                 
338                         case MemoryMappedFileAccess.ReadWriteExecute:
339                                 return PROT_WRITE | PROT_READ | PROT_EXEC;
340                                 
341                         case MemoryMappedFileAccess.Read:
342                         default:
343                                 return PROT_READ;
344                         }
345                 }
346
347                 static void ThrowErrorFromErrno (int errno) 
348                 {
349                         switch (errno) {
350                         case EINVAL:            throw new ArgumentException ();
351                         case ENAMETOOLONG:      throw new PathTooLongException ();
352                         default: throw new IOException ("Failed with errno " + errno);
353                         }
354                 }
355
356                 internal static int Open (string path, FileMode mode, long capacity, MemoryMappedFileAccess access)
357                 {
358                         long file_size = mono_filesize_from_path (path);
359                         if (file_size < 0)
360                                 throw new FileNotFoundException (path);
361
362                         if ((capacity == 0 && file_size == 0) || (capacity > file_size))
363                                 throw new ArgumentException ("capacity");
364
365                         int fd = open (path, ToUnixMode (mode) | ToUnixMode (access), DEFFILEMODE);
366
367                         if (fd == -1)
368                                 ThrowErrorFromErrno (Marshal.GetLastWin32Error ());
369                         return fd;
370                 }
371
372                 internal static void CloseFD (int fd)
373                 {
374                         close (fd);
375                 }
376
377                 internal static void Flush (int fd)
378                 {
379                         fsync (fd);
380                 }
381
382                 internal static bool Unmap (IntPtr map_addr, ulong map_size)
383                 {
384                         return munmap (map_addr, (IntPtr)map_size) == 0;
385                 }
386
387                 static int pagesize;
388
389                 internal static unsafe void Map (int file_handle, long offset, ref long size, MemoryMappedFileAccess access, out IntPtr map_addr, out int offset_diff)
390                 {
391                         if (pagesize == 0)
392                                 pagesize = getpagesize ();
393
394                         long fsize = mono_filesize_from_fd (file_handle);
395                         if (fsize < 0)
396                                 throw new FileNotFoundException ();
397
398                         if (size == 0 || size > fsize)
399                                 size = fsize;
400                         
401                         // Align offset
402                         long real_offset = offset & ~(pagesize - 1);
403
404                         offset_diff = (int)(offset - real_offset);
405
406                         map_addr = mmap (IntPtr.Zero, (IntPtr) size,
407                                                  ToUnixProts (access),
408                                                  access == MemoryMappedFileAccess.CopyOnWrite ? MAP_PRIVATE : MAP_SHARED,
409                                                  file_handle, real_offset);
410
411                         if (map_addr == (IntPtr)(-1))
412                                 throw new IOException ("mmap failed for fd#" + file_handle + "(" + offset + ", " + size + ")");
413                 }
414
415                 internal static void ConfigureFD (IntPtr handle, HandleInheritability inheritability)
416                 {
417                         int fd = (int)handle;
418                         int flags = fcntl (fd, F_GETFD, 0);
419                         if (inheritability == HandleInheritability.None)
420                                 flags &= ~FD_CLOEXEC;
421                         else
422                                 flags |= FD_CLOEXEC;
423                         fcntl (fd, F_SETFD, flags);
424                 }
425
426         }
427 #endif
428
429         public class MemoryMappedFile : IDisposable {
430                 MemoryMappedFileAccess fileAccess;
431                 string name;
432                 long fileCapacity;
433
434                 //
435                 // We allow the use of either the FileStream/keepOpen combo
436                 // or a Unix file descriptor.  This way we avoid the dependency on
437                 // Mono's io-layer having the Unix file descriptors mapped to
438                 // the same io-layer handle
439                 //
440                 FileStream stream;
441                 bool keepOpen;
442                 int unix_fd;
443
444                 public static MemoryMappedFile CreateFromFile (string path)
445                 {
446                         return CreateFromFile (path, FileMode.Open, null, 0, MemoryMappedFileAccess.ReadWrite);
447                 }
448
449                 public static MemoryMappedFile CreateFromFile (string path, FileMode mode)
450                 {
451                         return CreateFromFile (path, mode, null, 0, MemoryMappedFileAccess.ReadWrite);
452                 }
453
454                 public static MemoryMappedFile CreateFromFile (string path, FileMode mode, string mapName)
455                 {
456                         return CreateFromFile (path, mode, mapName, 0, MemoryMappedFileAccess.ReadWrite);
457                 }
458
459                 public static MemoryMappedFile CreateFromFile (string path, FileMode mode, string mapName, long capacity)
460                 {
461                         return CreateFromFile (path, mode, mapName, capacity, MemoryMappedFileAccess.ReadWrite);
462                 }
463
464                 public static MemoryMappedFile CreateFromFile (string path, FileMode mode, string mapName, long capacity, MemoryMappedFileAccess access)
465                 {
466                         if (path == null)
467                                 throw new ArgumentNullException ("path");
468                         if (path.Length == 0)
469                                 throw new ArgumentException ("path");
470                         if (mapName != null && mapName.Length == 0)
471                                 throw new ArgumentException ("mapName");
472                         if (mode == FileMode.Append)
473                                 throw new ArgumentException ("mode");                   
474
475                         int fd = MemoryMapImpl.Open (path, mode, capacity, access);
476                         
477                         return new MemoryMappedFile () {
478                                 unix_fd = fd,
479                                 fileAccess = access,
480                                 name = mapName,
481                                 fileCapacity = capacity
482                         };
483                 }
484
485 #if MOBILE
486                 public static MemoryMappedFile CreateFromFile (FileStream fileStream, string mapName, long capacity, MemoryMappedFileAccess access,
487                                                                HandleInheritability inheritability,
488                                                                bool leaveOpen)
489 #else
490                 [MonoLimitation ("memoryMappedFileSecurity is currently ignored")]
491                 public static MemoryMappedFile CreateFromFile (FileStream fileStream, string mapName, long capacity, MemoryMappedFileAccess access,
492                                                                MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability inheritability,
493                                                                bool leaveOpen)
494 #endif
495                 {
496                         if (fileStream == null)
497                                 throw new ArgumentNullException ("fileStream");
498                         if (mapName != null && mapName.Length == 0)
499                                 throw new ArgumentException ("mapName");
500                         if ((capacity == 0 && fileStream.Length == 0) || (capacity > fileStream.Length))
501                                 throw new ArgumentException ("capacity");
502
503                         MemoryMapImpl.ConfigureFD (fileStream.Handle, inheritability);
504                                 
505                         return new MemoryMappedFile () {
506                                 stream = fileStream,
507                                 fileAccess = access,
508                                 name = mapName,
509                                 fileCapacity = capacity,
510                                 keepOpen = leaveOpen
511                         };
512                 }
513
514                 [MonoLimitation ("CreateNew requires that mapName be a file name on Unix")]
515                 public static MemoryMappedFile CreateNew (string mapName, long capacity)
516                 {
517 #if MOBILE
518                         return CreateNew (mapName, capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.DelayAllocatePages, 0);
519 #else
520                         return CreateNew (mapName, capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.DelayAllocatePages, null, 0);
521 #endif
522                 }
523
524                 [MonoLimitation ("CreateNew requires that mapName be a file name on Unix")]
525                 public static MemoryMappedFile CreateNew (string mapName, long capacity, MemoryMappedFileAccess access) 
526                 {
527 #if MOBILE
528                         return CreateNew (mapName, capacity, access, MemoryMappedFileOptions.DelayAllocatePages, 0);
529 #else
530                         return CreateNew (mapName, capacity, access, MemoryMappedFileOptions.DelayAllocatePages, null, 0);
531 #endif
532                 }
533
534 #if MOBILE
535                 public static MemoryMappedFile CreateNew (string mapName, long capacity, MemoryMappedFileAccess access,
536                                                           MemoryMappedFileOptions options, 
537                                                           HandleInheritability handleInheritability)
538 #else
539                 [MonoLimitation ("CreateNew requires that mapName be a file name on Unix; options and memoryMappedFileSecurity are ignored")]
540                 public static MemoryMappedFile CreateNew (string mapName, long capacity, MemoryMappedFileAccess access,
541                                                           MemoryMappedFileOptions options, MemoryMappedFileSecurity memoryMappedFileSecurity,
542                                                           HandleInheritability inheritability)
543 #endif
544                 {
545                         return CreateFromFile (mapName, FileMode.CreateNew, mapName, capacity, access);
546                 }
547
548                 [MonoLimitation ("CreateOrOpen requires that mapName be a file name on Unix")]
549                 public static MemoryMappedFile CreateOrOpen (string mapName, long capacity)
550                 {
551                         return CreateOrOpen (mapName, capacity, MemoryMappedFileAccess.ReadWrite);
552                 }
553
554                 [MonoLimitation ("CreateOrOpen requires that mapName be a file name on Unix")]
555                 public static MemoryMappedFile CreateOrOpen (string mapName, long capacity, MemoryMappedFileAccess access)
556                 {
557                         return CreateFromFile (mapName, FileMode.OpenOrCreate, mapName, capacity, access); 
558                 }
559
560                 [MonoTODO]
561 #if MOBILE
562                 public static MemoryMappedFile CreateOrOpen (string mapName, long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, HandleInheritability inheritability)
563 #else
564                 public static MemoryMappedFile CreateOrOpen (string mapName, long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability inheritability)
565 #endif
566                 {
567                         throw new NotImplementedException ();
568                 }
569
570                 [MonoTODO]
571                 public static MemoryMappedFile OpenExisting (string mapName)
572                 {
573                         throw new NotImplementedException ();
574                 }
575
576                 [MonoTODO]
577                 public static MemoryMappedFile OpenExisting (string mapName, MemoryMappedFileRights desiredAccessRights)
578                 {
579                         throw new NotImplementedException ();
580                 }
581
582                 [MonoTODO]
583                 public static MemoryMappedFile OpenExisting (string mapName, MemoryMappedFileRights desiredAccessRights, HandleInheritability inheritability)
584                 {
585                         throw new NotImplementedException ();
586                 }
587
588                 public MemoryMappedViewStream CreateViewStream ()
589                 {
590                         return CreateViewStream (0, 0);
591                 }
592
593                 public MemoryMappedViewStream CreateViewStream (long offset, long size)
594                 {
595                         return CreateViewStream (offset, size, MemoryMappedFileAccess.ReadWrite);
596                 }
597
598                 public MemoryMappedViewStream CreateViewStream (long offset, long size, MemoryMappedFileAccess access)
599                 {
600                         return new MemoryMappedViewStream (stream != null ? (int)stream.Handle : unix_fd, offset, size, access);
601                 }
602
603                 public MemoryMappedViewAccessor CreateViewAccessor ()
604                 {
605                         return CreateViewAccessor (0, 0);
606                 }
607
608                 public MemoryMappedViewAccessor CreateViewAccessor (long offset, long size)
609                 {
610                         return CreateViewAccessor (offset, size, MemoryMappedFileAccess.ReadWrite);
611                 }
612
613                 public MemoryMappedViewAccessor CreateViewAccessor (long offset, long size, MemoryMappedFileAccess access)
614                 {
615                         int file_handle = stream != null ? (int) stream.Handle : unix_fd;
616                         
617                         return new MemoryMappedViewAccessor (file_handle, offset, size, access);
618                 }
619
620                 MemoryMappedFile ()
621                 {
622                 }
623
624                 public void Dispose ()
625                 {
626                         Dispose (true);
627                 }
628
629                 protected virtual void Dispose (bool disposing)
630                 {
631                         if (disposing){
632                                 if (stream != null){
633                                         if (keepOpen == false)
634                                                 stream.Close ();
635                                         unix_fd = -1;
636                                         stream = null;
637                                 }
638                                 if (unix_fd != -1) {
639                                         MemoryMapImpl.CloseFD (unix_fd);
640                                         unix_fd = -1;
641                                 }
642                         }
643                 }
644
645 #if !MOBILE
646                 [MonoTODO]
647                 public MemoryMappedFileSecurity GetAccessControl ()
648                 {
649                         throw new NotImplementedException ();
650                 }
651
652                 [MonoTODO]
653                 public void SetAccessControl (MemoryMappedFileSecurity memoryMappedFileSecurity)
654                 {
655                         throw new NotImplementedException ();
656                 }
657 #endif
658
659                 [MonoTODO]
660                 public SafeMemoryMappedFileHandle SafeMemoryMappedFileHandle {
661                         get {
662                                 throw new NotImplementedException ();
663                         }
664                 }
665         }
666 }
667
668 #endif