internal static MemoryMappedDataReaderFactory CreateUnix(string filename, bool mapAsImage)
        {
            if (!canTryUnix)
            {
                return(null);
            }

            var creator = new MemoryMappedDataReaderFactory(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($"mmap'd IO didn't work: {ex.Message}");
            }
            catch (EntryPointNotFoundException) {
            }
            catch (DllNotFoundException) {
            }
            canTryUnix = false;
            return(null);
        }
            public static void Mmap(MemoryMappedDataReaderFactory creator, bool mapAsImage)
            {
                using (var fileHandle = CreateFile(creator.filename, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero)) {
                    if (fileHandle.IsInvalid)
                    {
                        throw new IOException($"Could not open file {creator.filename} for reading. Error: {Marshal.GetLastWin32Error():X8}");
                    }

                    uint sizeLo = GetFileSize(fileHandle, out uint sizeHi);
                    int  hr;
                    if (sizeLo == INVALID_FILE_SIZE && (hr = Marshal.GetLastWin32Error()) != NO_ERROR)
                    {
                        throw new IOException($"Could not get file size. File: {creator.filename}, error: {hr:X8}");
                    }
                    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($"Could not create a file mapping object. File: {creator.filename}, error: {Marshal.GetLastWin32Error():X8}");
                        }
                        creator.data = MapViewOfFile(fileMapping, FILE_MAP_READ, 0, 0, UIntPtr.Zero);
                        if (creator.data == IntPtr.Zero)
                        {
                            throw new MemoryMappedIONotSupportedException($"Could not map file {creator.filename}. Error: {Marshal.GetLastWin32Error():X8}");
                        }
                        creator.length = (uint)fileSize;
                        creator.osType = OSType.Windows;
                        creator.stream = DataStreamFactory.Create((byte *)creator.data);
                    }
                }
            }
            public static void Mmap(MemoryMappedDataReaderFactory creator, bool mapAsImage)
            {
                int fd = open(creator.filename, O_RDONLY);

                try {
                    if (fd < 0)
                    {
                        throw new IOException($"Could not open file {creator.filename} for reading. Error: {fd}");
                    }

                    long   size;
                    IntPtr data;

                    if (IntPtr.Size == 4)
                    {
                        size = lseek32(fd, 0, SEEK_END);
                        if (size == -1)
                        {
                            throw new MemoryMappedIONotSupportedException($"Could not get length of {creator.filename} (lseek failed): {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($"Could not map file {creator.filename}. Error: {Marshal.GetLastWin32Error()}");
                        }
                    }
                    else
                    {
                        size = lseek64(fd, 0, SEEK_END);
                        if (size == -1)
                        {
                            throw new MemoryMappedIONotSupportedException($"Could not get length of {creator.filename} (lseek failed): {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($"Could not map file {creator.filename}. Error: {Marshal.GetLastWin32Error()}");
                        }
                    }

                    creator.data           = data;
                    creator.length         = (uint)size;
                    creator.origDataLength = size;
                    creator.osType         = OSType.Unix;
                    creator.stream         = DataStreamFactory.Create((byte *)creator.data);
                }
                finally {
                    if (fd >= 0)
                    {
                        close(fd);
                    }
                }
            }
Ejemplo n.º 4
0
 static DataReaderFactory CreateDataReaderFactory(string fileName, bool mapAsImage)
 {
     if (!isUnix)
     {
         return(MemoryMappedDataReaderFactory.CreateWindows(fileName, mapAsImage));
     }
     else
     {
         return(MemoryMappedDataReaderFactory.CreateUnix(fileName, mapAsImage));
     }
 }
        internal static MemoryMappedDataReaderFactory CreateWindows(string filename, bool mapAsImage)
        {
            if (!canTryWindows)
            {
                return(null);
            }

            var creator = new MemoryMappedDataReaderFactory(GetFullPath(filename));

            try {
                Windows.Mmap(creator, mapAsImage);
                return(creator);
            }
            catch (EntryPointNotFoundException) {
            }
            catch (DllNotFoundException) {
            }
            canTryWindows = false;
            return(null);
        }