5 // Zoltan Varga (vargaz@gmail.com)
7 // Copyright (C) 2009, Novell, Inc (http://www.novell.com)
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
33 using System.Collections.Generic;
34 using Microsoft.Win32.SafeHandles;
35 using Mono.Unix.Native;
36 using System.Runtime.InteropServices;
38 namespace System.IO.MemoryMappedFiles
40 public class MemoryMappedFile : IDisposable {
41 MemoryMappedFileAccess fileAccess;
47 public static MemoryMappedFile CreateFromFile (FileStream fileStream) {
48 if (fileStream == null)
49 throw new ArgumentNullException ("fileStream");
51 return new MemoryMappedFile () {
53 fileAccess = MemoryMappedFileAccess.ReadWrite
57 public static MemoryMappedFile CreateFromFile (string path)
59 return CreateFromFile (path, FileMode.Open, null, 0, MemoryMappedFileAccess.ReadWrite);
63 public static MemoryMappedFile CreateFromFile (string path, FileMode mode)
65 return CreateFromFile (path, mode, null, 0, MemoryMappedFileAccess.ReadWrite);
68 public static MemoryMappedFile CreateFromFile (string path, FileMode mode, string mapName)
70 return CreateFromFile (path, mode, mapName, 0, MemoryMappedFileAccess.ReadWrite);
73 public static MemoryMappedFile CreateFromFile (string path, FileMode mode, string mapName, long capacity)
75 return CreateFromFile (path, mode, mapName, capacity, MemoryMappedFileAccess.ReadWrite);
78 public static MemoryMappedFile CreateFromFile (string path, FileMode mode, string mapName, long capacity, MemoryMappedFileAccess access)
81 throw new ArgumentNullException ("path");
83 throw new ArgumentException ("path");
84 if (mapName != null && mapName.Length == 0)
85 throw new ArgumentException ("mapName");
86 var fileStream = File.Open (path, mode);
88 if ((capacity == 0 && fileStream.Length == 0) || (capacity > fileStream.Length)){
90 throw new ArgumentException ("capacity");
92 return new MemoryMappedFile () {
96 fileCapacity = capacity
100 public static void ConfigureUnixFD (IntPtr handle, HandleInheritability h)
102 // TODO: Mono.Posix is lacking O_CLOEXEC definitions for fcntl.
106 [DllImport("kernel32.dll", SetLastError = true)]
107 static extern bool SetHandleInformation (IntPtr hObject, int dwMask, int dwFlags);
108 public static void ConfigureWindowsFD (IntPtr handle, HandleInheritability h)
110 SetHandleInformation (handle, 1 /* FLAG_INHERIT */, h == HandleInheritability.None ? 0 : 1);
113 [MonoLimitation ("memoryMappedFileSecurity is currently ignored")]
114 public static MemoryMappedFile CreateFromFile (FileStream fileStream, string mapName, long capacity, MemoryMappedFileAccess access,
115 MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability inheritability,
118 if (fileStream == null)
119 throw new ArgumentNullException ("fileStream");
120 if (mapName != null && mapName.Length == 0)
121 throw new ArgumentException ("mapName");
122 if ((capacity == 0 && fileStream.Length == 0) || (capacity > fileStream.Length))
123 throw new ArgumentException ("capacity");
126 ConfigureUnixFD (fileStream.Handle, inheritability);
128 ConfigureWindowsFD (fileStream.Handle, inheritability);
130 return new MemoryMappedFile () {
134 fileCapacity = capacity,
141 public static MemoryMappedFile CreateNew (string mapName, long capacity)
143 throw new NotImplementedException ();
147 public static MemoryMappedFile CreateNew (string mapName, long capacity, MemoryMappedFileAccess access)
149 throw new NotImplementedException ();
154 public static MemoryMappedFile CreateNew (string mapName, long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability handleInheritability) {
155 throw new NotImplementedException ();
160 public static MemoryMappedFile CreateOrOpen (string mapName, long capacity) {
161 throw new NotImplementedException ();
165 public static MemoryMappedFile CreateOrOpen (string mapName, long capacity, MemoryMappedFileAccess access) {
166 throw new NotImplementedException ();
171 public static MemoryMappedFile CreateOrOpen (string mapName, long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability handleInheritability) {
172 throw new NotImplementedException ();
176 public MemoryMappedViewStream CreateViewStream ()
178 return CreateViewStream (0, 0);
181 public MemoryMappedViewStream CreateViewStream (long offset, long size)
183 return CreateViewStream (offset, size, MemoryMappedFileAccess.ReadWrite);
187 public MemoryMappedViewStream CreateViewStream (long offset, long size, MemoryMappedFileAccess access)
189 return new MemoryMappedViewStream (stream, offset, size, access);
192 public MemoryMappedViewAccessor CreateViewAccessor ()
194 return CreateViewAccessor (0, 0);
197 public MemoryMappedViewAccessor CreateViewAccessor (long offset, long size)
199 return CreateViewAccessor (offset, size, MemoryMappedFileAccess.ReadWrite);
203 public MemoryMappedViewAccessor CreateViewAccessor (long offset, long size, MemoryMappedFileAccess access)
205 return new MemoryMappedViewAccessor (stream, offset, size, access);
212 public void Dispose ()
217 protected virtual void Dispose (bool disposing)
220 if (stream != null && keepOpen == false)
227 public SafeMemoryMappedFileHandle SafeMemoryMappedFileHandle {
229 throw new NotImplementedException ();
235 static MmapProts ToUnixProts (MemoryMappedFileAccess access)
240 case MemoryMappedFileAccess.ReadWrite:
241 return MmapProts.PROT_WRITE | MmapProts.PROT_READ;
244 case MemoryMappedFileAccess.Write:
245 return MmapProts.PROT_WRITE;
247 case MemoryMappedFileAccess.CopyOnWrite:
248 return MmapProts.PROT_WRITE | MmapProts.PROT_READ;
250 case MemoryMappedFileAccess.ReadExecute:
251 return MmapProts.PROT_EXEC;
253 case MemoryMappedFileAccess.ReadWriteExecute:
254 return MmapProts.PROT_WRITE | MmapProts.PROT_READ | MmapProts.PROT_EXEC;
256 case MemoryMappedFileAccess.Read:
258 return MmapProts.PROT_READ;
263 internal static unsafe void MapPosix (FileStream file, long offset, long size, MemoryMappedFileAccess access, out IntPtr map_addr, out int offset_diff)
266 pagesize = Syscall.getpagesize ();
268 long fsize = file.Length;
270 if (size == 0 || size > fsize)
274 long real_offset = offset & ~(pagesize - 1);
276 offset_diff = (int)(offset - real_offset);
278 // FIXME: Need to determine the unix fd for the file, Handle is only
279 // equal to it by accident
281 // The new API no longer uses FileStream everywhere, but exposes instead
282 // the filename (with one exception), we could move this API to use
283 // file descriptors instead of the FileStream plus its Handle.
285 map_addr = Syscall.mmap (IntPtr.Zero, (ulong) size,
286 ToUnixProts (access),
287 access == MemoryMappedFileAccess.CopyOnWrite ? MmapFlags.MAP_PRIVATE : MmapFlags.MAP_SHARED,
288 (int)file.Handle, real_offset);
290 if (map_addr == (IntPtr)(-1))
291 throw new IOException ("mmap failed for " + file + "(" + offset + ", " + size + ")");
294 internal static void FlushPosix (FileStream file)
296 Syscall.fsync ((int) file.Handle);
299 internal static bool UnmapPosix (IntPtr map_addr, ulong map_size)
301 return Syscall.munmap (map_addr, map_size) == 0;