Beispiel #1
0
 public void ThrowsArgumentNullExceptionForNullBuffers()
 {
     using (SafeFileHandle handle = File.OpenHandle(GetTestFilePath(), FileMode.CreateNew, FileAccess.Write))
     {
         AssertExtensions.Throws <ArgumentNullException>("buffers", () => RandomAccess.Read(handle, buffers: null, 0));
     }
 }
Beispiel #2
0
 public void ThrowsOnWriteAccess()
 {
     using (SafeFileHandle handle = GetHandleToExistingFile(FileAccess.Write))
     {
         Assert.Throws <UnauthorizedAccessException>(() => RandomAccess.Read(handle, new Memory <byte>[] { new byte[1] }, 0));
     }
 }
Beispiel #3
0
 public void ThrowsArgumentNullExceptionForNullBuffers(FileOptions options)
 {
     using (SafeFileHandle handle = GetHandleToExistingFile(FileAccess.Read, options))
     {
         AssertExtensions.Throws <ArgumentNullException>("buffers", () => RandomAccess.Read(handle, buffers: null, 0));
     }
 }
Beispiel #4
0
        public void ReadsBytesFromGivenFileAtGivenOffset(FileOptions options)
        {
            const int fileSize = 4_001;
            string    filePath = GetTestFilePath();

            byte[] expected = RandomNumberGenerator.GetBytes(fileSize);
            File.WriteAllBytes(filePath, expected);

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Open, options: options))
            {
                byte[] actual  = new byte[fileSize + 1];
                int    current = 0;
                int    total   = 0;

                do
                {
                    Span <byte> buffer = actual.AsSpan(total, Math.Min(actual.Length - total, fileSize / 4));

                    current = RandomAccess.Read(handle, buffer, fileOffset: total);

                    Assert.InRange(current, 0, buffer.Length);

                    total += current;
                } while (current != 0);

                Assert.Equal(fileSize, total);
                Assert.Equal(expected, actual.Take(total).ToArray());
            }
        }
Beispiel #5
0
        public void ShouldReuseBuffer()
        {
            var ra = new RandomAccess(new byte[] { 1, 2, 3, 4 });

            ra.Byte();
            var read = ra.Read(3);

            Assert.AreEqual(3, read.Length);
            Assert.AreEqual(0, read.Position);
            Assert.AreEqual(2, read.Byte());
            Assert.AreEqual(3, read.Byte());
            Assert.AreEqual(4, read.Byte());

            read.JumpAbsolute(0);
            Assert.AreEqual(2, read.Byte());

            read.JumpRelative(1);
            Assert.AreEqual(4, read.Byte());

            read.JumpAbsolute(1);

            var read2 = read.Read(2);

            Assert.AreEqual(2, read2.Length);
            Assert.AreEqual(0, read2.Position);
            Assert.AreEqual(3, read2.Byte());
            Assert.AreEqual(4, read2.Byte());
        }
Beispiel #6
0
        public async Task ReadUsingSingleBuffer(bool asyncOperation, bool asyncHandle)
        {
            const int fileSize = 1_000_000; // 1 MB
            string    filePath = GetTestFilePath();

            byte[] expected = RandomNumberGenerator.GetBytes(fileSize);
            File.WriteAllBytes(filePath, expected);

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Open, options: GetFileOptions(asyncHandle)))
                using (SectorAlignedMemory <byte> buffer = SectorAlignedMemory <byte> .Allocate(Environment.SystemPageSize))
                {
                    int current = 0;
                    int total   = 0;

                    do
                    {
                        current = asyncOperation
                        ? await RandomAccess.ReadAsync(handle, buffer.Memory, fileOffset : total)
                        : RandomAccess.Read(handle, buffer.GetSpan(), fileOffset: total);

                        Assert.True(expected.AsSpan(total, current).SequenceEqual(buffer.GetSpan().Slice(0, current)));

                        total += current;
                    }while (current != 0);

                    Assert.Equal(fileSize, total);
                }
        }
Beispiel #7
0
            static async Task Validate(SafeFileHandle handle, FileOptions options, bool[] syncWrites, bool[] syncReads)
            {
                byte[] writeBuffer = new byte[1];
                byte[] readBuffer  = new byte[2];
                long   fileOffset  = 0;

                foreach (bool syncWrite in syncWrites)
                {
                    foreach (bool syncRead in syncReads)
                    {
                        writeBuffer[0] = (byte)fileOffset;

                        if (syncWrite)
                        {
                            RandomAccess.Write(handle, writeBuffer, fileOffset);
                        }
                        else
                        {
                            await RandomAccess.WriteAsync(handle, writeBuffer, fileOffset);
                        }

                        Assert.Equal(writeBuffer.Length, syncRead ? RandomAccess.Read(handle, readBuffer, fileOffset) : await RandomAccess.ReadAsync(handle, readBuffer, fileOffset));

                        Assert.Equal(writeBuffer[0], readBuffer[0]);

                        fileOffset += 1;
                    }
                }
            }
Beispiel #8
0
 public void ThrowsOnWriteAccess(FileOptions options)
 {
     using (SafeFileHandle handle = GetHandleToExistingFile(FileAccess.Write, options))
     {
         Assert.Throws <UnauthorizedAccessException>(() => RandomAccess.Read(handle, new byte[1], 0));
     }
 }
Beispiel #9
0
        public TpsHeader(RandomAccess rx)
        {
            Data = rx ?? throw new ArgumentNullException(nameof(rx));

            Address = rx.LongLE();

            if (Address != 0)
            {
                throw new NotATopSpeedFileException("File does not start with 0x00000000. It is not a TopSpeed file or it may be encrypted.");
            }

            HeaderSize = rx.ShortLE();

            var header = rx.Read(HeaderSize - 6);

            FileLength1             = header.LongLE();
            FileLength2             = header.LongLE();
            MagicNumber             = header.FixedLengthString(4);
            Zeroes                  = header.ShortLE();
            LastIssuedRow           = header.LongBE();
            Changes                 = header.LongLE();
            ManagementPageReference = header.ToFileOffset(header.LongLE());

            PageStart = header.ToFileOffset(header.LongArrayLE((0x110 - 0x20) / 4));
            PageEnd   = header.ToFileOffset(header.LongArrayLE((0x200 - 0x110) / 4));
        }
Beispiel #10
0
        public void ShouldFailBeyondBuffer()
        {
            var ra = new RandomAccess(new byte[] { 1, 2, 3, 4 });

            ra.Byte();
            var read = ra.Read(3);

            Assert.Throws <IndexOutOfRangeException>(() => read.LongLE());
        }
Beispiel #11
0
        public void ShouldFailBeforeBuffer()
        {
            var ra = new RandomAccess(new byte[] { 1, 2, 3, 4 });

            ra.Byte();
            var read = ra.Read(3);

            read.JumpAbsolute(-1);

            Assert.Throws <IndexOutOfRangeException>(() => read.Byte());
        }
Beispiel #12
0
    /// <summary>
    /// 读取二进制文件。
    /// </summary>
    /// <param name="path">给定的文件路径。</param>
    /// <param name="fileOffset">给定的读取偏移量。</param>
    /// <returns>返回字节数组。</returns>
    public static byte[] ReadBinaryFile(this string path, long fileOffset)
    {
        using (var handle = File.OpenHandle(path))
        {
            var length = RandomAccess.GetLength(handle);
            var buffer = new byte[length - fileOffset];

            var readLength = RandomAccess.Read(handle, buffer, fileOffset);
            return(buffer);
        }
    }
Beispiel #13
0
        public void ZeroesTheFileContentsWhenExtendingTheFile(FileOptions options)
        {
            using (SafeFileHandle handle = File.OpenHandle(GetTestFilePath(), FileMode.CreateNew, FileAccess.Write, options: options))
            {
                RandomAccess.SetLength(handle, FileSize);

                byte[] buffer = new byte[FileSize + 1];
                Assert.Equal(FileSize, RandomAccess.Read(handle, buffer, 0));
                Assert.All(buffer, @byte => Assert.Equal(0, @byte));
            }
        }
    private void ReadFileTable(SafeFileHandle handle)
    {
        // Read the 12 byte footer at the end of the file
        Span <byte> fileFooter = stackalloc byte[12];

        if (RandomAccess.Read(_fileHandle, fileFooter, _fileLength - fileFooter.Length) < fileFooter.Length)
        {
            throw new InvalidDataException("Couldn't read file footer");
        }

        var signature     = BitConverter.ToUInt32(fileFooter[..4]);
Beispiel #15
0
        public void ReadToAnEmptyBufferReturnsZero()
        {
            string filePath = GetTestFilePath();

            File.WriteAllBytes(filePath, new byte[1]);

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Open))
            {
                Assert.Equal(0, RandomAccess.Read(handle, new Memory <byte>[] { Array.Empty <byte>() }, fileOffset: 0));
            }
        }
Beispiel #16
0
        public void ReadFromBeyondEndOfFileReturnsZero(FileOptions options)
        {
            string filePath = GetTestFilePath();

            File.WriteAllBytes(filePath, new byte[100]);

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Open, options: options))
            {
                long eof = RandomAccess.GetLength(handle);
                Assert.Equal(0, RandomAccess.Read(handle, new byte[1], fileOffset: eof + 1));
            }
        }
Beispiel #17
0
        public void CanUseStackAllocatedMemory(FileOptions options)
        {
            string filePath = GetTestFilePath();

            File.WriteAllBytes(filePath, new byte[1] {
                3
            });

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Open, options: options))
            {
                Span <byte> stackAllocated = stackalloc byte[2];
                Assert.Equal(1, RandomAccess.Read(handle, stackAllocated, fileOffset: 0));
                Assert.Equal(3, stackAllocated[0]);
            }
        }
Beispiel #18
0
        public void ReadToTheSameBufferOverwritesContent()
        {
            string filePath = GetTestFilePath();

            File.WriteAllBytes(filePath, new byte[3] {
                1, 2, 3
            });

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Open))
            {
                byte[] buffer = new byte[1];
                Assert.Equal(buffer.Length + buffer.Length, RandomAccess.Read(handle, Enumerable.Repeat(buffer.AsMemory(), 2).ToList(), fileOffset: 0));
                Assert.Equal(2, buffer[0]);
            }
        }
        /// <summary>Read the database for the specified terminal from the specified directory.</summary>
        /// <param name="term">The identifier for the terminal.</param>
        /// <param name="directoryPath">The path to the directory containing terminfo database files.</param>
        /// <returns>The database, or null if it could not be found.</returns>
        internal static Database?ReadDatabase(string?term, string?directoryPath)
        {
            if (string.IsNullOrEmpty(term) || string.IsNullOrEmpty(directoryPath))
            {
                return(null);
            }

            Span <char>    stackBuffer = stackalloc char[256];
            SafeFileHandle?fd;

            if (!TryOpen(string.Create(null, stackBuffer, $"{directoryPath}/{term[0]}/{term}"), out fd) &&       // /directory/termFirstLetter/term      (Linux)
                !TryOpen(string.Create(null, stackBuffer, $"{directoryPath}/{(int)term[0]:X}/{term}"), out fd))  // /directory/termFirstLetterAsHex/term (Mac)
            {
                return(null);
            }

            using (fd)
            {
                // Read in all of the terminfo data
                long      termInfoLength    = RandomAccess.GetLength(fd);
                const int MaxTermInfoLength = 4096; // according to the term and tic man pages, 4096 is the terminfo file size max
                const int HeaderLength      = 12;
                if (termInfoLength <= HeaderLength || termInfoLength > MaxTermInfoLength)
                {
                    throw new InvalidOperationException(SR.IO_TermInfoInvalid);
                }

                byte[] data       = new byte[(int)termInfoLength];
                long   fileOffset = 0;
                do
                {
                    int bytesRead = RandomAccess.Read(fd, new Span <byte>(data, (int)fileOffset, (int)(termInfoLength - fileOffset)), fileOffset);
                    if (bytesRead == 0)
                    {
                        throw new InvalidOperationException(SR.IO_TermInfoInvalid);
                    }

                    fileOffset += bytesRead;
                } while (fileOffset < termInfoLength);

                // Create the database from the data
                return(new Database(term, data));
            }
        }
Beispiel #20
0
        private static bool CompareTimeZoneFile(string filePath, byte[] buffer, byte[] rawData)
        {
            try
            {
                // bufferSize == 1 used to avoid unnecessary buffer in FileStream
                using (SafeFileHandle sfh = File.OpenHandle(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    long fileLength = RandomAccess.GetLength(sfh);
                    if (fileLength == rawData.Length)
                    {
                        int index = 0;
                        int count = rawData.Length;

                        while (count > 0)
                        {
                            int n = RandomAccess.Read(sfh, buffer.AsSpan(index, count), index);
                            if (n == 0)
                            {
                                ThrowHelper.ThrowEndOfFileException();
                            }

                            int end = index + n;
                            for (; index < end; index++)
                            {
                                if (buffer[index] != rawData[index])
                                {
                                    return(false);
                                }
                            }

                            count -= n;
                        }

                        return(true);
                    }
                }
            }
            catch (IOException) { }
            catch (SecurityException) { }
            catch (UnauthorizedAccessException) { }

            return(false);
        }
Beispiel #21
0
        /// <summary>
        /// Creates a new <see cref="TpsRecord"/>. This is typically done on the first of a list.
        /// </summary>
        /// <param name="rx">The data to read from.</param>
        public TpsRecord(RandomAccess rx)
        {
            if (rx == null)
            {
                throw new ArgumentNullException(nameof(rx));
            }

            Flags = rx.Byte();

            if ((Flags & 0xC0) != 0xC0)
            {
                throw new ArgumentException($"Cannot construct a TpsRecord without record lengths (0x{rx.ToHex2(Flags)})");
            }

            RecordLength = rx.ShortLE();
            HeaderLength = rx.ShortLE();

            Data = rx.Read(RecordLength);

            BuildHeader();
        }
Beispiel #22
0
        public TpsPage(RandomAccess rx)
        {
            if (rx == null)
            {
                throw new ArgumentNullException(nameof(rx));
            }

            Records = new List <TpsRecord>();

            Address = rx.LongLE();
            Size    = rx.ShortLE();

            var header = rx.Read(Size - 6);

            SizeUncompressed = header.ShortLE();
            SizeUncompressedWithoutHeader = header.ShortLE();
            RecordCount = header.ShortLE();
            Flags       = header.Byte();

            CompressedData = header.Read(Size - 13);
        }
Beispiel #23
0
        public void ReadsBytesFromGivenFileAtGivenOffset()
        {
            const int fileSize = 4_001;
            string    filePath = GetTestFilePath();

            byte[] expected = RandomNumberGenerator.GetBytes(fileSize);
            File.WriteAllBytes(filePath, expected);

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Open))
            {
                byte[] actual  = new byte[fileSize + 1];
                long   current = 0;
                long   total   = 0;

                do
                {
                    int           firstBufferLength = (int)Math.Min(actual.Length - total, fileSize / 4);
                    Memory <byte> buffer_1          = actual.AsMemory((int)total, firstBufferLength);
                    Memory <byte> buffer_2          = actual.AsMemory((int)total + firstBufferLength);

                    current = RandomAccess.Read(
                        handle,
                        new Memory <byte>[]
                    {
                        buffer_1,
                        Array.Empty <byte>(),
                        buffer_2
                    },
                        fileOffset: total);

                    Assert.InRange(current, 0, buffer_1.Length + buffer_2.Length);

                    total += current;
                } while (current != 0);

                Assert.Equal(fileSize, total);
                Assert.Equal(expected, actual.Take((int)total).ToArray());
            }
        }
Beispiel #24
0
        public async Task ReadAsyncUsingMultipleBuffers(bool asyncOperation, bool asyncHandle)
        {
            const int fileSize = 1_000_000; // 1 MB
            string    filePath = GetTestFilePath();

            byte[] expected = RandomNumberGenerator.GetBytes(fileSize);
            File.WriteAllBytes(filePath, expected);

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Open, options: GetFileOptions(asyncHandle)))
                using (SectorAlignedMemory <byte> buffer_1 = SectorAlignedMemory <byte> .Allocate(Environment.SystemPageSize))
                    using (SectorAlignedMemory <byte> buffer_2 = SectorAlignedMemory <byte> .Allocate(Environment.SystemPageSize))
                    {
                        long current = 0;
                        long total   = 0;

                        IReadOnlyList <Memory <byte> > buffers = new Memory <byte>[]
                        {
                            buffer_1.Memory,
                            buffer_2.Memory,
                        };

                        do
                        {
                            current = asyncOperation
                        ? await RandomAccess.ReadAsync(handle, buffers, fileOffset : total)
                        : RandomAccess.Read(handle, buffers, fileOffset: total);

                            int takeFromFirst = Math.Min(buffer_1.Memory.Length, (int)current);
                            Assert.True(expected.AsSpan((int)total, takeFromFirst).SequenceEqual(buffer_1.GetSpan().Slice(0, takeFromFirst)));
                            int takeFromSecond = (int)current - takeFromFirst;
                            Assert.True(expected.AsSpan((int)total + takeFromFirst, takeFromSecond).SequenceEqual(buffer_2.GetSpan().Slice(0, takeFromSecond)));

                            total += current;
                        } while (current == buffer_1.Memory.Length + buffer_2.Memory.Length);

                        Assert.Equal(fileSize, total);
                    }
        }
Beispiel #25
0
        public async Task ReadUsingSingleBuffer(bool async)
        {
            const int fileSize = 1_000_000; // 1 MB
            string    filePath = GetTestFilePath();

            byte[] expected = RandomNumberGenerator.GetBytes(fileSize);
            File.WriteAllBytes(filePath, expected);

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Open,
                                                           options: FileOptions.Asynchronous | NoBuffering)) // to use Scatter&Gather APIs on Windows the handle MUST be opened for async IO
                using (SectorAlignedMemory <byte> buffer = SectorAlignedMemory <byte> .Allocate(Environment.SystemPageSize))
                {
                    int current = 0;
                    int total   = 0;

                    // From https://docs.microsoft.com/en-us/windows/win32/fileio/file-buffering:
                    // "File access sizes, including the optional file offset in the OVERLAPPED structure,
                    // if specified, must be for a number of bytes that is an integer multiple of the volume sector size."
                    // So if buffer and physical sector size is 4096 and the file size is 4097:
                    // the read from offset=0 reads 4096 bytes
                    // the read from offset=4096 reads 1 byte
                    // the read from offset=4097 THROWS (Invalid argument, offset is not a multiple of sector size!)
                    // That is why we stop at the first incomplete read (the next one would throw).
                    // It's possible to get 0 if we are lucky and file size is a multiple of physical sector size.
                    do
                    {
                        current = async
                        ? await RandomAccess.ReadAsync(handle, buffer.Memory, fileOffset : total)
                        : RandomAccess.Read(handle, buffer.GetSpan(), fileOffset: total);

                        Assert.True(expected.AsSpan(total, current).SequenceEqual(buffer.GetSpan().Slice(0, current)));

                        total += current;
                    }while (current == buffer.Memory.Length);

                    Assert.Equal(fileSize, total);
                }
        }
Beispiel #26
0
        public uint HashFileLocationsUsingRandomAccessCrc32()
        {
            SafeFileHandle handle = File.OpenHandle(FilePath, FileMode.Open);

            byte[] buffer = new byte[1024 * 1024 * 2];

            uint hash1 = 0;
            uint hash2 = 0;
            uint hash3 = 0;

            for (int i = 0; i < 10; i++)
            {
                RandomAccess.Read(handle, buffer, 0);
                hash1 = HashUtils.CRC32(buffer);

                RandomAccess.Read(handle, buffer, Count / 2);
                hash2 = HashUtils.CRC32(buffer);

                RandomAccess.Read(handle, buffer, Count - 1024 * 1024 * 2);
                hash3 = HashUtils.CRC32(buffer);
            }

            return((uint)HashCode.Combine(hash1, hash2, hash3));
        }
Beispiel #27
0
 protected override long MethodUnderTest(SafeFileHandle handle, byte[] bytes, long fileOffset)
 => RandomAccess.Read(handle, new Memory <byte>[] { bytes }, fileOffset);
Beispiel #28
0
 protected override int MethodUnderTest(SafeFileHandle handle, byte[] bytes, long fileOffset)
 => RandomAccess.Read(handle, bytes, fileOffset);