public void GetFileLength()
        {
            NtfsFileSystem ntfs = new FileSystemSource().NtfsFileSystem();

            ntfs.OpenFile(@"AFILE.TXT", FileMode.Create).Close();
            Assert.AreEqual(0, ntfs.GetFileLength("AFILE.TXT"));

            using (var stream = ntfs.OpenFile(@"AFILE.TXT", FileMode.Open))
            {
                stream.Write(new byte[14325], 0, 14325);
            }
            Assert.AreEqual(14325, ntfs.GetFileLength("AFILE.TXT"));

            using (var attrStream = ntfs.OpenFile(@"AFILE.TXT:altstream", FileMode.Create))
            {
                attrStream.Write(new byte[122], 0, 122);
            }
            Assert.AreEqual(122, ntfs.GetFileLength("AFILE.TXT:altstream"));


            // Test NTFS options for hardlink behaviour
            ntfs.CreateDirectory("Dir");
            ntfs.CreateHardLink("AFILE.TXT", @"Dir\OtherLink.txt");

            using (var stream = ntfs.OpenFile("AFILE.TXT", FileMode.Open, FileAccess.ReadWrite))
            {
                stream.SetLength(50);
            }
            Assert.AreEqual(50, ntfs.GetFileLength("AFILE.TXT"));
            Assert.AreEqual(14325, ntfs.GetFileLength(@"Dir\OtherLink.txt"));

            ntfs.NtfsOptions.FileLengthFromDirectoryEntries = false;

            Assert.AreEqual(50, ntfs.GetFileLength(@"Dir\OtherLink.txt"));
        }
        public void ShortNames()
        {
            NtfsFileSystem ntfs = new FileSystemSource().NtfsFileSystem();

            // Check we can find a short name in the same directory
            using (Stream s = ntfs.OpenFile("ALongFileName.txt", FileMode.CreateNew)) {}
            ntfs.SetShortName("ALongFileName.txt", "ALONG~01.TXT");
            Assert.AreEqual("ALONG~01.TXT", ntfs.GetShortName("ALongFileName.txt"));
            Assert.IsTrue(ntfs.FileExists("ALONG~01.TXT"));

            // Check path handling
            ntfs.CreateDirectory("DIR");
            using (Stream s = ntfs.OpenFile(@"DIR\ALongFileName2.txt", FileMode.CreateNew)) { }
            ntfs.SetShortName(@"DIR\ALongFileName2.txt", "ALONG~02.TXT");
            Assert.AreEqual("ALONG~02.TXT", ntfs.GetShortName(@"DIR\ALongFileName2.txt"));
            Assert.IsTrue(ntfs.FileExists(@"DIR\ALONG~02.TXT"));

            // Check we can open a file by the short name
            using (Stream s = ntfs.OpenFile("ALONG~01.TXT", FileMode.Open)) { }

            // Delete the long name, and make sure the file is gone
            ntfs.DeleteFile("ALONG~01.TXT");
            Assert.IsFalse(ntfs.FileExists("ALONG~01.TXT"));

            // Delete the short name, and make sure the file is gone
            ntfs.DeleteFile(@"DIR\ALONG~02.TXT");
            Assert.IsFalse(ntfs.FileExists(@"DIR\ALongFileName2.txt"));
        }
        public void Fragmented()
        {
            NtfsFileSystem ntfs = new FileSystemSource().NtfsFileSystem();

            ntfs.CreateDirectory(@"DIR");

            byte[] buffer = new byte[4096];

            for (int i = 0; i < 2500; ++i)
            {
                using (var stream = ntfs.OpenFile(@"DIR\file" + i + ".bin", FileMode.Create, FileAccess.ReadWrite))
                {
                    stream.Write(buffer, 0, buffer.Length);
                }

                using (var stream = ntfs.OpenFile(@"DIR\" + i + ".bin", FileMode.Create, FileAccess.ReadWrite))
                {
                    stream.Write(buffer, 0, buffer.Length);
                }
            }

            for (int i = 0; i < 2500; ++i)
            {
                ntfs.DeleteFile(@"DIR\file" + i + ".bin");
            }

            // Create fragmented file (lots of small writes)
            using (var stream = ntfs.OpenFile(@"DIR\fragmented.bin", FileMode.Create, FileAccess.ReadWrite))
            {
                for (int i = 0; i < 2500; ++i)
                {
                    stream.Write(buffer, 0, buffer.Length);
                }
            }

            // Try a large write
            byte[] largeWriteBuffer = new byte[200 * 1024];
            for (int i = 0; i < largeWriteBuffer.Length / 4096; ++i)
            {
                largeWriteBuffer[i * 4096] = (byte)i;
            }
            using (var stream = ntfs.OpenFile(@"DIR\fragmented.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                stream.Position = stream.Length - largeWriteBuffer.Length;
                stream.Write(largeWriteBuffer, 0, largeWriteBuffer.Length);
            }

            // And a large read
            byte[] largeReadBuffer = new byte[largeWriteBuffer.Length];
            using (var stream = ntfs.OpenFile(@"DIR\fragmented.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                stream.Position = stream.Length - largeReadBuffer.Length;
                stream.Read(largeReadBuffer, 0, largeReadBuffer.Length);
            }

            Assert.AreEqual(largeWriteBuffer, largeReadBuffer);
        }
        public void AclInheritance()
        {
            NtfsFileSystem ntfs = new FileSystemSource().NtfsFileSystem();

            RawSecurityDescriptor sd = new RawSecurityDescriptor("O:BAG:BAD:(A;OICINP;GA;;;BA)");
            ntfs.CreateDirectory("dir");
            ntfs.SetSecurity("dir", sd);

            ntfs.CreateDirectory(@"dir\subdir");
            RawSecurityDescriptor inheritedSd = ntfs.GetSecurity(@"dir\subdir");

            Assert.NotNull(inheritedSd);
            Assert.AreEqual("O:BAG:BAD:(A;ID;GA;;;BA)", inheritedSd.GetSddlForm(AccessControlSections.All));

            using (ntfs.OpenFile(@"dir\subdir\file", FileMode.Create, FileAccess.ReadWrite)) { }
            inheritedSd = ntfs.GetSecurity(@"dir\subdir\file");
            Assert.NotNull(inheritedSd);
            Assert.AreEqual("O:BAG:BAD:", inheritedSd.GetSddlForm(AccessControlSections.All));
        }
        public void AclInheritance()
        {
            NtfsFileSystem ntfs = new FileSystemSource().NtfsFileSystem();

            RawSecurityDescriptor sd = new RawSecurityDescriptor("O:BAG:BAD:(A;OICINP;GA;;;BA)");

            ntfs.CreateDirectory("dir");
            ntfs.SetSecurity("dir", sd);

            ntfs.CreateDirectory(@"dir\subdir");
            RawSecurityDescriptor inheritedSd = ntfs.GetSecurity(@"dir\subdir");

            Assert.NotNull(inheritedSd);
            Assert.AreEqual("O:BAG:BAD:(A;ID;GA;;;BA)", inheritedSd.GetSddlForm(AccessControlSections.All));

            using (ntfs.OpenFile(@"dir\subdir\file", FileMode.Create, FileAccess.ReadWrite)) { }
            inheritedSd = ntfs.GetSecurity(@"dir\subdir\file");
            Assert.NotNull(inheritedSd);
            Assert.AreEqual("O:BAG:BAD:", inheritedSd.GetSddlForm(AccessControlSections.All));
        }
        public void ReparsePoints_NonEmpty()
        {
            NtfsFileSystem ntfs = new FileSystemSource().NtfsFileSystem();

            ntfs.CreateDirectory("dir");
            ntfs.SetReparsePoint("dir", new ReparsePoint(123, new byte[] { 4, 5, 6 }));

            ReparsePoint rp = ntfs.GetReparsePoint("dir");

            Assert.AreEqual(123, rp.Tag);
            Assert.IsNotNull(rp.Content);
            Assert.AreEqual(3, rp.Content.Length);
        }
        public void DeleteShortNameDir()
        {
            NtfsFileSystem ntfs = new FileSystemSource().NtfsFileSystem();

            ntfs.CreateDirectory(@"\TestLongName1\TestLongName2");
            ntfs.SetShortName(@"\TestLongName1\TestLongName2", "TESTLO~1");

            Assert.IsTrue(ntfs.DirectoryExists(@"\TestLongName1\TESTLO~1"));
            Assert.IsTrue(ntfs.DirectoryExists(@"\TestLongName1\TestLongName2"));

            ntfs.DeleteDirectory(@"\TestLongName1", true);

            Assert.IsFalse(ntfs.DirectoryExists(@"\TestLongName1"));
        }
        public void HardLinkCount()
        {
            NtfsFileSystem ntfs = new FileSystemSource().NtfsFileSystem();

            using (Stream s = ntfs.OpenFile("ALongFileName.txt", FileMode.CreateNew)) { }
            Assert.AreEqual(1, ntfs.GetHardLinkCount("ALongFileName.txt"));

            ntfs.CreateHardLink("ALongFileName.txt", "AHardLink.TXT");
            Assert.AreEqual(2, ntfs.GetHardLinkCount("ALongFileName.txt"));

            ntfs.CreateDirectory("DIR");
            ntfs.CreateHardLink(@"ALongFileName.txt", @"DIR\SHORTLNK.TXT");
            Assert.AreEqual(3, ntfs.GetHardLinkCount("ALongFileName.txt"));

            // If we enumerate short names, then the initial long name results in two 'hardlinks'
            ntfs.NtfsOptions.HideDosFileNames = false;
            Assert.AreEqual(4, ntfs.GetHardLinkCount("ALongFileName.txt"));
        }
        public void MoveLongName()
        {
            NtfsFileSystem ntfs = new FileSystemSource().NtfsFileSystem();

            using (Stream s = ntfs.OpenFile("ALongFileName.txt", FileMode.CreateNew)) { }

            Assert.IsTrue(ntfs.FileExists("ALONGF~1.TXT"));

            ntfs.MoveFile("ALongFileName.txt", "ADifferentLongFileName.txt");

            Assert.IsFalse(ntfs.FileExists("ALONGF~1.TXT"));
            Assert.IsTrue(ntfs.FileExists("ADIFFE~1.TXT"));

            ntfs.CreateDirectory("ALongDirectoryName");
            Assert.IsTrue(ntfs.DirectoryExists("ALONGD~1"));

            ntfs.MoveDirectory("ALongDirectoryName", "ADifferentLongDirectoryName");
            Assert.IsFalse(ntfs.DirectoryExists("ALONGD~1"));
            Assert.IsTrue(ntfs.DirectoryExists("ADIFFE~1"));
        }
        public void DeleteShortNameDir()
        {
            NtfsFileSystem ntfs = new FileSystemSource().NtfsFileSystem();

            ntfs.CreateDirectory(@"\TestLongName1\TestLongName2");
            ntfs.SetShortName(@"\TestLongName1\TestLongName2", "TESTLO~1");

            Assert.IsTrue(ntfs.DirectoryExists(@"\TestLongName1\TESTLO~1"));
            Assert.IsTrue(ntfs.DirectoryExists(@"\TestLongName1\TestLongName2"));

            ntfs.DeleteDirectory(@"\TestLongName1", true);

            Assert.IsFalse(ntfs.DirectoryExists(@"\TestLongName1"));
        }
        public void ShortNames()
        {
            NtfsFileSystem ntfs = new FileSystemSource().NtfsFileSystem();

            // Check we can find a short name in the same directory
            using (Stream s = ntfs.OpenFile("ALongFileName.txt", FileMode.CreateNew)) {}
            ntfs.SetShortName("ALongFileName.txt", "ALONG~01.TXT");
            Assert.AreEqual("ALONG~01.TXT", ntfs.GetShortName("ALongFileName.txt"));
            Assert.IsTrue(ntfs.FileExists("ALONG~01.TXT"));

            // Check path handling
            ntfs.CreateDirectory("DIR");
            using (Stream s = ntfs.OpenFile(@"DIR\ALongFileName2.txt", FileMode.CreateNew)) { }
            ntfs.SetShortName(@"DIR\ALongFileName2.txt", "ALONG~02.TXT");
            Assert.AreEqual("ALONG~02.TXT", ntfs.GetShortName(@"DIR\ALongFileName2.txt"));
            Assert.IsTrue(ntfs.FileExists(@"DIR\ALONG~02.TXT"));

            // Check we can open a file by the short name
            using (Stream s = ntfs.OpenFile("ALONG~01.TXT", FileMode.Open)) { }

            // Delete the long name, and make sure the file is gone
            ntfs.DeleteFile("ALONG~01.TXT");
            Assert.IsFalse(ntfs.FileExists("ALONG~01.TXT"));

            // Delete the short name, and make sure the file is gone
            ntfs.DeleteFile(@"DIR\ALONG~02.TXT");
            Assert.IsFalse(ntfs.FileExists(@"DIR\ALongFileName2.txt"));
        }
        public void ReparsePoints_NonEmpty()
        {
            NtfsFileSystem ntfs = new FileSystemSource().NtfsFileSystem();

            ntfs.CreateDirectory("dir");
            ntfs.SetReparsePoint("dir", new ReparsePoint(123, new byte[] { 4, 5, 6 }));

            ReparsePoint rp = ntfs.GetReparsePoint("dir");

            Assert.AreEqual(123, rp.Tag);
            Assert.IsNotNull(rp.Content);
            Assert.AreEqual(3, rp.Content.Length);
        }
        public void MoveLongName()
        {
            NtfsFileSystem ntfs = new FileSystemSource().NtfsFileSystem();

            using (Stream s = ntfs.OpenFile("ALongFileName.txt", FileMode.CreateNew)) { }

            Assert.IsTrue(ntfs.FileExists("ALONGF~1.TXT"));

            ntfs.MoveFile("ALongFileName.txt", "ADifferentLongFileName.txt");

            Assert.IsFalse(ntfs.FileExists("ALONGF~1.TXT"));
            Assert.IsTrue(ntfs.FileExists("ADIFFE~1.TXT"));

            ntfs.CreateDirectory("ALongDirectoryName");
            Assert.IsTrue(ntfs.DirectoryExists("ALONGD~1"));

            ntfs.MoveDirectory("ALongDirectoryName", "ADifferentLongDirectoryName");
            Assert.IsFalse(ntfs.DirectoryExists("ALONGD~1"));
            Assert.IsTrue(ntfs.DirectoryExists("ADIFFE~1"));
        }
        public void HardLinkCount()
        {
            NtfsFileSystem ntfs = new FileSystemSource().NtfsFileSystem();

            using (Stream s = ntfs.OpenFile("ALongFileName.txt", FileMode.CreateNew)) { }
            Assert.AreEqual(1, ntfs.GetHardLinkCount("ALongFileName.txt"));

            ntfs.CreateHardLink("ALongFileName.txt", "AHardLink.TXT");
            Assert.AreEqual(2, ntfs.GetHardLinkCount("ALongFileName.txt"));

            ntfs.CreateDirectory("DIR");
            ntfs.CreateHardLink(@"ALongFileName.txt", @"DIR\SHORTLNK.TXT");
            Assert.AreEqual(3, ntfs.GetHardLinkCount("ALongFileName.txt"));

            // If we enumerate short names, then the initial long name results in two 'hardlinks'
            ntfs.NtfsOptions.HideDosFileNames = false;
            Assert.AreEqual(4, ntfs.GetHardLinkCount("ALongFileName.txt"));
        }
        public void GetFileLength()
        {
            NtfsFileSystem ntfs = new FileSystemSource().NtfsFileSystem();

            ntfs.OpenFile(@"AFILE.TXT", FileMode.Create).Close();
            Assert.AreEqual(0, ntfs.GetFileLength("AFILE.TXT"));

            using (var stream = ntfs.OpenFile(@"AFILE.TXT", FileMode.Open))
            {
                stream.Write(new byte[14325], 0, 14325);
            }
            Assert.AreEqual(14325, ntfs.GetFileLength("AFILE.TXT"));

            using (var attrStream = ntfs.OpenFile(@"AFILE.TXT:altstream", FileMode.Create))
            {
                attrStream.Write(new byte[122], 0, 122);
            }
            Assert.AreEqual(122, ntfs.GetFileLength("AFILE.TXT:altstream"));

            // Test NTFS options for hardlink behaviour
            ntfs.CreateDirectory("Dir");
            ntfs.CreateHardLink("AFILE.TXT", @"Dir\OtherLink.txt");

            using (var stream = ntfs.OpenFile("AFILE.TXT", FileMode.Open, FileAccess.ReadWrite))
            {
                stream.SetLength(50);
            }
            Assert.AreEqual(50, ntfs.GetFileLength("AFILE.TXT"));
            Assert.AreEqual(14325, ntfs.GetFileLength(@"Dir\OtherLink.txt"));

            ntfs.NtfsOptions.FileLengthFromDirectoryEntries = false;

            Assert.AreEqual(50, ntfs.GetFileLength(@"Dir\OtherLink.txt"));
        }
        public void Fragmented()
        {
            NtfsFileSystem ntfs = new FileSystemSource().NtfsFileSystem();

            ntfs.CreateDirectory(@"DIR");

            byte[] buffer = new byte[4096];

            for(int i = 0; i < 2500; ++i)
            {
                using(var stream = ntfs.OpenFile(@"DIR\file" + i + ".bin", FileMode.Create, FileAccess.ReadWrite))
                {
                    stream.Write(buffer, 0,buffer.Length);
                }

                using(var stream = ntfs.OpenFile(@"DIR\" + i + ".bin", FileMode.Create, FileAccess.ReadWrite))
                {
                    stream.Write(buffer, 0,buffer.Length);
                }
            }

            for (int i = 0; i < 2500; ++i)
            {
                ntfs.DeleteFile(@"DIR\file" + i + ".bin");
            }

            // Create fragmented file (lots of small writes)
            using (var stream = ntfs.OpenFile(@"DIR\fragmented.bin", FileMode.Create, FileAccess.ReadWrite))
            {
                for (int i = 0; i < 2500; ++i)
                {
                    stream.Write(buffer, 0, buffer.Length);
                }
            }

            // Try a large write
            byte[] largeWriteBuffer = new byte[200 * 1024];
            for (int i = 0; i < largeWriteBuffer.Length / 4096; ++i)
            {
                largeWriteBuffer[i * 4096] = (byte)i;
            }
            using (var stream = ntfs.OpenFile(@"DIR\fragmented.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                stream.Position = stream.Length - largeWriteBuffer.Length;
                stream.Write(largeWriteBuffer, 0, largeWriteBuffer.Length);
            }

            // And a large read
            byte[] largeReadBuffer = new byte[largeWriteBuffer.Length];
            using (var stream = ntfs.OpenFile(@"DIR\fragmented.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                stream.Position = stream.Length - largeReadBuffer.Length;
                stream.Read(largeReadBuffer, 0, largeReadBuffer.Length);
            }

            Assert.AreEqual(largeWriteBuffer, largeReadBuffer);
        }