public static void Mmap(MemoryMappedFileStreamCreator creator, bool mapAsImage) { using (var fileHandle = CreateFile(creator.theFileName, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero)) { if (fileHandle.IsInvalid) throw new IOException(string.Format("Could not open file {0} for reading. Error: {1:X8}", creator.theFileName, Marshal.GetLastWin32Error())); uint sizeHi; uint sizeLo = GetFileSize(fileHandle, out sizeHi); int hr; if (sizeLo == INVALID_FILE_SIZE && (hr = Marshal.GetLastWin32Error()) != NO_ERROR) throw new IOException(string.Format("Could not get file size. File: {0}, error: {1:X8}", creator.theFileName, hr)); var fileSize = ((long)sizeHi << 32) | sizeLo; using (var fileMapping = CreateFileMapping(fileHandle, IntPtr.Zero, PAGE_READONLY | (mapAsImage ? SEC_IMAGE : 0), 0, 0, null)) { if (fileMapping.IsInvalid) throw new MemoryMappedIONotSupportedException(string.Format("Could not create a file mapping object. File: {0}, error: {1:X8}", creator.theFileName, Marshal.GetLastWin32Error())); creator.data = MapViewOfFile(fileMapping, FILE_MAP_READ, 0, 0, UIntPtr.Zero); if (creator.data == IntPtr.Zero) throw new MemoryMappedIONotSupportedException(string.Format("Could not map file {0}. Error: {1:X8}", creator.theFileName, Marshal.GetLastWin32Error())); creator.dataLength = fileSize; creator.osType = OSType.Windows; } } }
/// <summary> /// Creates a new <see cref="MemoryMappedFileStreamCreator"/> if supported or returns /// <c>null</c> if the OS functions aren't supported. /// </summary> /// <remarks>If <paramref name="mapAsImage"/> is <c>true</c>, then the created /// <see cref="UnmanagedMemoryStreamCreator"/> that is used internally by the class, /// can only access bytes up to the file size, not to the end of the mapped image. You must /// set <see cref="UnmanagedMemoryStreamCreator.Length"/> to the correct image length to access the full image.</remarks> /// <param name="fileName">Name of the file</param> /// <param name="mapAsImage">NOT SUPPORTED. <c>true</c> if we should map it as an executable</param> /// <exception cref="IOException">If we can't open/map the file</exception> internal static MemoryMappedFileStreamCreator CreateUnix(string fileName, bool mapAsImage) { if (!canTryUnix) return null; var creator = new MemoryMappedFileStreamCreator(); creator.theFileName = GetFullPath(fileName); try { Unix.Mmap(creator, mapAsImage); if (mapAsImage) { // Only check this if we know that mmap() works, i.e., if above call succeeds creator.Dispose(); throw new ArgumentException("mapAsImage == true is not supported on this OS"); } return creator; } catch (MemoryMappedIONotSupportedException ex) { Debug.WriteLine(string.Format("mmap'd IO didn't work: {0}", ex.Message)); } catch (EntryPointNotFoundException) { } catch (DllNotFoundException) { } canTryUnix = false; return null; }
private static MemoryMappedFileStreamCreator CreateMemoryMappedFileStreamCreator(string fileName, bool mapAsImage) { if (!isUnix) { return(MemoryMappedFileStreamCreator.CreateWindows(fileName, mapAsImage)); } else { return(MemoryMappedFileStreamCreator.CreateUnix(fileName, mapAsImage)); } }
public static void Mmap(MemoryMappedFileStreamCreator creator, bool mapAsImage) { int fd = open(creator.theFileName, O_RDONLY); try { if (fd < 0) throw new IOException(string.Format("Could not open file {0} for reading. Error: {1}", creator.theFileName, fd)); long size; IntPtr data; if (IntPtr.Size == 4) { size = lseek32(fd, 0, SEEK_END); if (size == -1) throw new MemoryMappedIONotSupportedException(string.Format("Could not get length of {0} (lseek failed): {1}", creator.theFileName, Marshal.GetLastWin32Error())); data = mmap32(IntPtr.Zero, (IntPtr)size, PROT_READ, MAP_PRIVATE, fd, 0); if (data == new IntPtr(-1) || data == IntPtr.Zero) throw new MemoryMappedIONotSupportedException(string.Format("Could not map file {0}. Error: {1}", creator.theFileName, Marshal.GetLastWin32Error())); } else { size = lseek64(fd, 0, SEEK_END); if (size == -1) throw new MemoryMappedIONotSupportedException(string.Format("Could not get length of {0} (lseek failed): {1}", creator.theFileName, Marshal.GetLastWin32Error())); data = mmap64(IntPtr.Zero, (IntPtr)size, PROT_READ, MAP_PRIVATE, fd, 0); if (data == new IntPtr(-1) || data == IntPtr.Zero) throw new MemoryMappedIONotSupportedException(string.Format("Could not map file {0}. Error: {1}", creator.theFileName, Marshal.GetLastWin32Error())); } creator.data = data; creator.dataLength = size; creator.origDataLength = creator.dataLength; creator.osType = OSType.Unix; } finally { if (fd >= 0) close(fd); } }
/// <summary> /// Creates a new <see cref="MemoryMappedFileStreamCreator"/> if supported or returns /// <c>null</c> if the OS functions aren't supported. /// </summary> /// <remarks>If <paramref name="mapAsImage"/> is <c>true</c>, then the created /// <see cref="UnmanagedMemoryStreamCreator"/> that is used internally by the class, /// can only access bytes up to the file size, not to the end of the mapped image. You must /// set <see cref="UnmanagedMemoryStreamCreator.Length"/> to the correct image length to access the full image.</remarks> /// <param name="fileName">Name of the file</param> /// <param name="mapAsImage"><c>true</c> if we should map it as an executable</param> /// <exception cref="IOException">If we can't open/map the file</exception> internal static MemoryMappedFileStreamCreator CreateWindows(string fileName, bool mapAsImage) { if (!canTryWindows) return null; var creator = new MemoryMappedFileStreamCreator(); creator.theFileName = GetFullPath(fileName); try { Windows.Mmap(creator, mapAsImage); return creator; } catch (EntryPointNotFoundException) { } catch (DllNotFoundException) { } canTryWindows = false; return null; }