Beispiel #1
0
        public virtual FileRecord CreateFile(MftSegmentReference parentDirectory, string fileName, bool isDirectory)
        {
            // Worst case scenrario: the MFT might be full and the parent directory index requires multiple splits
            if (NumberOfFreeClusters < 24)
            {
                throw new DiskFullException();
            }
            FileRecord parentDirectoryRecord = GetFileRecord(parentDirectory);

            m_mftLock.AcquireWriterLock(Timeout.Infinite);
            IndexData parentDirectoryIndex = new IndexData(this, parentDirectoryRecord, AttributeType.FileName);

            if (parentDirectoryIndex.ContainsFileName(fileName))
            {
                m_mftLock.ReleaseWriterLock();
                throw new AlreadyExistsException();
            }

            List <FileNameRecord> fileNameRecords = IndexHelper.GenerateFileNameRecords(parentDirectory, fileName, isDirectory, m_generateDosNames, parentDirectoryIndex);
            uint       transactionID = m_logClient.AllocateTransactionID();
            FileRecord fileRecord    = m_mft.CreateFile(fileNameRecords, transactionID);

            // Update parent directory index
            foreach (FileNameRecord fileNameRecord in fileNameRecords)
            {
                parentDirectoryIndex.AddEntry(fileRecord.BaseSegmentReference, fileNameRecord.GetBytes());
            }
            m_logClient.WriteForgetTransactionRecord(transactionID);
            m_logClient.WriteRestartRecord(this.MajorVersion, true);
            m_mftLock.ReleaseWriterLock();

            return(fileRecord);
        }
Beispiel #2
0
        public virtual KeyValuePairList <MftSegmentReference, FileNameRecord> GetFileNameRecordsInDirectory(MftSegmentReference directoryReference)
        {
            KeyValuePairList <MftSegmentReference, FileNameRecord> result;

            lock (m_mftLock)
            {
                FileRecord directoryRecord = GetFileRecord(directoryReference);
                if (!directoryRecord.IsDirectory)
                {
                    throw new ArgumentException("directoryReference belongs to a file record which is not a directory");
                }
                IndexData indexData = new IndexData(this, directoryRecord, AttributeType.FileName);
                result = indexData.GetAllFileNameRecords();
            }

            for (int index = 0; index < result.Count; index++)
            {
                bool isMetaFile = (result[index].Key.SegmentNumber < MasterFileTable.FirstUserSegmentNumber);
                if (result[index].Value.Flags == FileNameFlags.DOS || isMetaFile)
                {
                    // The same FileRecord can have multiple FileNameRecord entries, each with its own namespace
                    result.RemoveAt(index);
                    index--;
                }
            }
            return(result);
        }
Beispiel #3
0
        public virtual void DeleteFile(FileRecord fileRecord)
        {
            MftSegmentReference parentDirectory       = fileRecord.ParentDirectoryReference;
            FileRecord          parentDirectoryRecord = GetFileRecord(parentDirectory);
            IndexData           parentDirectoryIndex  = new IndexData(this, parentDirectoryRecord, AttributeType.FileName);

            // Update parent directory index
            List <FileNameRecord> fileNameRecords = fileRecord.FileNameRecords;

            foreach (FileNameRecord fileNameRecord in fileNameRecords)
            {
                parentDirectoryIndex.RemoveEntry(fileNameRecord.GetBytes());
            }

            // Deallocate all data clusters
            foreach (AttributeRecord atttributeRecord in fileRecord.Attributes)
            {
                if (atttributeRecord is NonResidentAttributeRecord)
                {
                    NonResidentAttributeData attributeData = new NonResidentAttributeData(this, fileRecord, (NonResidentAttributeRecord)atttributeRecord);
                    attributeData.Truncate(0);
                }
            }

            m_mft.DeleteFile(fileRecord);
        }
Beispiel #4
0
        public virtual KeyValuePairList <MftSegmentReference, FileNameRecord> GetFileNameRecordsInDirectory(MftSegmentReference directoryReference)
        {
            FileRecord directoryRecord = GetFileRecord(directoryReference);
            KeyValuePairList <MftSegmentReference, FileNameRecord> result = null;

            if (directoryRecord != null && directoryRecord.IsDirectory)
            {
                m_mftLock.AcquireReaderLock(Timeout.Infinite);
                IndexData indexData = new IndexData(this, directoryRecord, AttributeType.FileName);
                result = indexData.GetAllFileNameRecords();
                m_mftLock.ReleaseReaderLock();

                for (int index = 0; index < result.Count; index++)
                {
                    bool isMetaFile = (result[index].Key.SegmentNumber < MasterFileTable.FirstUserSegmentNumber);
                    if (result[index].Value.Flags == FileNameFlags.DOS || isMetaFile)
                    {
                        // The same FileRecord can have multiple FileNameRecord entries, each with its own namespace
                        result.RemoveAt(index);
                        index--;
                    }
                }
            }
            return(result);
        }
Beispiel #5
0
        public virtual void DeleteFile(FileRecord fileRecord)
        {
            MftSegmentReference parentDirectory       = fileRecord.ParentDirectoryReference;
            FileRecord          parentDirectoryRecord = GetFileRecord(parentDirectory);

            m_mftLock.AcquireWriterLock(Timeout.Infinite);
            IndexData parentDirectoryIndex = new IndexData(this, parentDirectoryRecord, AttributeType.FileName);

            uint transactionID = m_logClient.AllocateTransactionID();
            // Update parent directory index
            List <FileNameRecord> fileNameRecords = fileRecord.FileNameRecords;

            foreach (FileNameRecord fileNameRecord in fileNameRecords)
            {
                parentDirectoryIndex.RemoveEntry(fileNameRecord.GetBytes());
            }

            // Deallocate all data clusters
            foreach (AttributeRecord atttributeRecord in fileRecord.Attributes)
            {
                if (atttributeRecord is NonResidentAttributeRecord)
                {
                    NonResidentAttributeData attributeData = new NonResidentAttributeData(this, fileRecord, (NonResidentAttributeRecord)atttributeRecord);
                    attributeData.Truncate(0);
                }
            }

            m_mft.DeleteFile(fileRecord, transactionID);
            m_logClient.WriteForgetTransactionRecord(transactionID);
            m_logClient.WriteRestartRecord(this.MajorVersion, true);
            m_mftLock.ReleaseWriterLock();
        }
Beispiel #6
0
        public virtual FileRecord CreateFile(MftSegmentReference parentDirectory, string fileName, bool isDirectory)
        {
            // Worst case scenrario: the MFT might be full and the parent directory index requires multiple splits
            if (NumberOfFreeClusters < 24)
            {
                throw new DiskFullException();
            }
            FileRecord parentDirectoryRecord = GetFileRecord(parentDirectory);
            IndexData  parentDirectoryIndex  = new IndexData(this, parentDirectoryRecord, AttributeType.FileName);

            if (parentDirectoryIndex.ContainsFileName(fileName))
            {
                throw new AlreadyExistsException();
            }

            List <FileNameRecord> fileNameRecords = IndexHelper.GenerateFileNameRecords(parentDirectory, fileName, isDirectory, m_generateDosNames, parentDirectoryIndex);
            FileRecord            fileRecord      = m_mft.CreateFile(fileNameRecords);

            // Update parent directory index
            foreach (FileNameRecord fileNameRecord in fileNameRecords)
            {
                parentDirectoryIndex.AddEntry(fileRecord.BaseSegmentReference, fileNameRecord.GetBytes());
            }

            return(fileRecord);
        }
Beispiel #7
0
        public virtual void MoveFile(FileRecord fileRecord, MftSegmentReference newParentDirectory, string newFileName)
        {
            // Worst case scenrario: the new parent directory index requires multiple splits
            if (NumberOfFreeClusters < 4)
            {
                throw new DiskFullException();
            }

            FileRecord oldParentDirectoryRecord = GetFileRecord(fileRecord.ParentDirectoryReference);
            IndexData  oldParentDirectoryIndex  = new IndexData(this, oldParentDirectoryRecord, AttributeType.FileName);
            IndexData  newParentDirectoryIndex;

            if (fileRecord.ParentDirectoryReference == newParentDirectory)
            {
                newParentDirectoryIndex = oldParentDirectoryIndex;
            }
            else
            {
                FileRecord newParentDirectoryRecord = GetFileRecord(newParentDirectory);
                newParentDirectoryIndex = new IndexData(this, newParentDirectoryRecord, AttributeType.FileName);
                if (newParentDirectoryIndex.ContainsFileName(newFileName))
                {
                    throw new AlreadyExistsException();
                }
            }

            List <FileNameRecord> fileNameRecords = fileRecord.FileNameRecords;

            foreach (FileNameRecord fileNameRecord in fileNameRecords)
            {
                oldParentDirectoryIndex.RemoveEntry(fileNameRecord.GetBytes());
            }

            DateTime       creationTime        = fileRecord.FileNameRecord.CreationTime;
            DateTime       modificationTime    = fileRecord.FileNameRecord.ModificationTime;
            DateTime       mftModificationTime = fileRecord.FileNameRecord.MftModificationTime;
            DateTime       lastAccessTime      = fileRecord.FileNameRecord.LastAccessTime;
            ulong          allocatedLength     = fileRecord.FileNameRecord.AllocatedLength;
            ulong          fileSize            = fileRecord.FileNameRecord.FileSize;
            FileAttributes fileAttributes      = fileRecord.FileNameRecord.FileAttributes;
            ushort         packedEASize        = fileRecord.FileNameRecord.PackedEASize;

            fileNameRecords = IndexHelper.GenerateFileNameRecords(newParentDirectory, newFileName, fileRecord.IsDirectory, m_generateDosNames, newParentDirectoryIndex, creationTime, modificationTime, mftModificationTime, lastAccessTime, allocatedLength, fileSize, fileAttributes, packedEASize);
            fileRecord.RemoveAttributeRecords(AttributeType.FileName, String.Empty);
            foreach (FileNameRecord fileNameRecord in fileNameRecords)
            {
                FileNameAttributeRecord fileNameAttribute = (FileNameAttributeRecord)fileRecord.CreateAttributeRecord(AttributeType.FileName, String.Empty);
                fileNameAttribute.IsIndexed = true;
                fileNameAttribute.Record    = fileNameRecord;
            }
            UpdateFileRecord(fileRecord);

            foreach (FileNameRecord fileNameRecord in fileNameRecords)
            {
                newParentDirectoryIndex.AddEntry(fileRecord.BaseSegmentReference, fileNameRecord.GetBytes());
            }
        }
Beispiel #8
0
        public virtual FileRecord GetFileRecord(string path)
        {
            if (path != String.Empty && !path.StartsWith(@"\"))
            {
                throw new InvalidPathException(String.Format("The path '{0}' is invalid", path));
            }

            if (path.EndsWith(@"\"))
            {
                path = path.Substring(0, path.Length - 1);
            }

            if (path == String.Empty)
            {
                return(GetFileRecord(MasterFileTable.RootDirSegmentReference));
            }

            string[]            components         = path.Substring(1).Split('\\');
            MftSegmentReference directoryReference = MasterFileTable.RootDirSegmentReference;

            lock (m_mftLock)
            {
                for (int index = 0; index < components.Length; index++)
                {
                    FileRecord directoryRecord = GetFileRecord(directoryReference);
                    if (index < components.Length - 1)
                    {
                        if (!directoryRecord.IsDirectory)
                        {
                            throw new InvalidPathException(String.Format("The path '{0}' is invalid", path));
                        }
                        IndexData indexData = new IndexData(this, directoryRecord, AttributeType.FileName);
                        directoryReference = indexData.FindFileNameRecordSegmentReference(components[index]);
                        if (directoryReference == null)
                        {
                            throw new DirectoryNotFoundException(String.Format("Could not find part of the path '{0}'", path));
                        }
                    }
                    else // Last component
                    {
                        IndexData           indexData     = new IndexData(this, directoryRecord, AttributeType.FileName);
                        MftSegmentReference fileReference = indexData.FindFileNameRecordSegmentReference(components[index]);
                        if (fileReference == null)
                        {
                            throw new FileNotFoundException(String.Format("Could not find file '{0}'", path));
                        }
                        FileRecord fileRecord = GetFileRecord(fileReference);
                        if (!fileRecord.IsMetaFile)
                        {
                            return(fileRecord);
                        }
                    }
                }
            }
            // We should never get here
            throw new InvalidPathException();
        }
Beispiel #9
0
        public virtual FileRecord GetFileRecord(string path)
        {
            if (path != String.Empty && !path.StartsWith(@"\"))
            {
                throw new ArgumentException("Invalid path");
            }

            if (path.EndsWith(@"\"))
            {
                path = path.Substring(0, path.Length - 1);
            }

            if (path == String.Empty)
            {
                return(GetFileRecord(MasterFileTable.RootDirSegmentReference));
            }

            string[]            components         = path.Substring(1).Split('\\');
            MftSegmentReference directoryReference = MasterFileTable.RootDirSegmentReference;

            for (int index = 0; index < components.Length; index++)
            {
                FileRecord directoryRecord = GetFileRecord(directoryReference);
                if (index < components.Length - 1)
                {
                    if (!directoryRecord.IsDirectory)
                    {
                        return(null);
                    }
                    IndexData indexData = new IndexData(this, directoryRecord, AttributeType.FileName);
                    directoryReference = indexData.FindFileNameRecordSegmentReference(components[index]);
                    if (directoryReference == null)
                    {
                        return(null);
                    }
                }
                else // Last component
                {
                    IndexData           indexData     = new IndexData(this, directoryRecord, AttributeType.FileName);
                    MftSegmentReference fileReference = indexData.FindFileNameRecordSegmentReference(components[index]);
                    if (fileReference == null)
                    {
                        return(null);
                    }
                    FileRecord fileRecord = GetFileRecord(fileReference);
                    if (fileRecord != null && !fileRecord.IsMetaFile)
                    {
                        return(fileRecord);
                    }
                }
            }

            return(null);
        }
Beispiel #10
0
 internal void UpdateDirectoryIndex(MftSegmentReference parentDirectory, List <FileNameRecord> fileNameRecords)
 {
     lock (m_mftLock)
     {
         FileRecord parentDirectoryRecord = GetFileRecord(parentDirectory);
         IndexData  parentDirectoryIndex  = new IndexData(this, parentDirectoryRecord, AttributeType.FileName);
         foreach (FileNameRecord fileNameRecord in fileNameRecords)
         {
             parentDirectoryIndex.UpdateFileNameRecord(fileNameRecord);
         }
     }
 }
Beispiel #11
0
        private void UpdateFileNameRecords()
        {
            List <FileNameRecord> fileNameRecords = m_fileRecord.FileNameRecords;

            foreach (FileNameRecord fileNameRecord in fileNameRecords)
            {
                fileNameRecord.AllocatedLength = this.Data.AllocatedLength;
                fileNameRecord.FileSize        = this.Data.Length;
            }
            m_volume.UpdateFileRecord(m_fileRecord);

            // Update directory index
            MftSegmentReference parentDirectory       = m_fileRecord.ParentDirectoryReference;
            FileRecord          parentDirectoryRecord = m_volume.GetFileRecord(parentDirectory);
            IndexData           parentDirectoryIndex  = new IndexData(m_volume, parentDirectoryRecord, AttributeType.FileName);

            foreach (FileNameRecord fileNameRecord in fileNameRecords)
            {
                parentDirectoryIndex.UpdateFileNameRecord(fileNameRecord);
            }
        }
Beispiel #12
0
        public override void Delete(string path)
        {
            FileRecord fileRecord = m_volume.GetFileRecord(path);

            if (fileRecord != null)
            {
                if (fileRecord.IsDirectory)
                {
                    IndexData directoryIndex = new IndexData(m_volume, fileRecord, AttributeType.FileName);
                    if (!directoryIndex.IsEmpty)
                    {
                        throw new DirectoryNotEmptyException();
                    }
                }
                m_volume.DeleteFile(fileRecord);
            }
            else
            {
                throw new FileNotFoundException();
            }
        }
Beispiel #13
0
        public virtual void DeleteFile(FileRecord fileRecord)
        {
            lock (m_mftLock)
            {
                MftSegmentReference parentDirectory       = fileRecord.ParentDirectoryReference;
                FileRecord          parentDirectoryRecord = GetFileRecord(parentDirectory);
                IndexData           parentDirectoryIndex  = new IndexData(this, parentDirectoryRecord, AttributeType.FileName);

                if (fileRecord.IsDirectory)
                {
                    IndexData directoryIndex = new IndexData(this, fileRecord, AttributeType.FileName);
                    if (!directoryIndex.IsEmpty)
                    {
                        throw new DirectoryNotEmptyException();
                    }
                }

                uint transactionID = m_logClient.AllocateTransactionID();
                // Update parent directory index
                List <FileNameRecord> fileNameRecords = fileRecord.FileNameRecords;
                foreach (FileNameRecord fileNameRecord in fileNameRecords)
                {
                    parentDirectoryIndex.RemoveEntry(fileNameRecord.GetBytes());
                }

                // Deallocate all data clusters
                foreach (AttributeRecord atttributeRecord in fileRecord.Attributes)
                {
                    if (atttributeRecord is NonResidentAttributeRecord)
                    {
                        NonResidentAttributeData attributeData = new NonResidentAttributeData(this, fileRecord, (NonResidentAttributeRecord)atttributeRecord);
                        attributeData.Truncate(0);
                    }
                }

                m_mft.DeleteFile(fileRecord, transactionID);
                m_logClient.WriteForgetTransactionRecord(transactionID);
                m_logClient.WriteRestartRecord(true);
            }
        }
Beispiel #14
0
        public static string GenerateDosName(IndexData parentDirectoryIndex, string fileName)
        {
            string nameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);
            string extension            = Path.GetExtension(fileName);

            nameWithoutExtension = ConvertToDosCharacters(nameWithoutExtension).ToUpper();
            if (extension.Length > 0)
            {
                extension = "." + ConvertToDosCharacters(extension.Substring(1)).ToUpper();
            }
            if (nameWithoutExtension.Length > 8)
            {
                nameWithoutExtension = nameWithoutExtension.Substring(0, 6) + "~1";
            }
            if (extension.Length > 4)
            {
                extension = extension.Substring(0, 4);
            }

            int    index = 1;
            string shortNameWithoutExtension;

            while (index <= 0xFFFFFF)
            {
                string suffix          = "~" + index.ToString("X");
                int    nameCharsToKeep = Math.Min(nameWithoutExtension.Length, 8 - suffix.Length);
                shortNameWithoutExtension = nameWithoutExtension.Substring(0, nameCharsToKeep) + suffix;
                string dosFileName = shortNameWithoutExtension + extension;
                if (!parentDirectoryIndex.ContainsFileName(dosFileName))
                {
                    return(dosFileName);
                }
                index++;
            }

            // Extremely unlikely that we will ever get here
            throw new NotSupportedException(String.Format("Could not find an available DOS name for '{0}'", fileName));
        }
Beispiel #15
0
        public virtual FileRecord CreateFile(MftSegmentReference parentDirectory, string fileName, bool isDirectory)
        {
            if (fileName.Length > FileNameRecord.MaxFileNameLength)
            {
                throw new InvalidNameException();
            }

            // Worst case scenrario: the MFT might be full and the parent directory index requires multiple splits.
            // We assume IndexData.ExtendGranularity is bigger than or equal to the number of splits.
            if (NumberOfFreeClusters < m_mft.NumberOfClustersRequiredToExtend + NumberOfClustersRequiredToExtendIndex)
            {
                throw new DiskFullException();
            }

            lock (m_mftLock)
            {
                FileRecord parentDirectoryRecord = GetFileRecord(parentDirectory);
                IndexData  parentDirectoryIndex  = new IndexData(this, parentDirectoryRecord, AttributeType.FileName);

                if (parentDirectoryIndex.ContainsFileName(fileName))
                {
                    throw new AlreadyExistsException();
                }

                List <FileNameRecord> fileNameRecords = IndexHelper.GenerateFileNameRecords(parentDirectory, fileName, isDirectory, GenerateDosNames, parentDirectoryIndex);
                uint       transactionID = m_logClient.AllocateTransactionID();
                FileRecord fileRecord    = m_mft.CreateFile(fileNameRecords, transactionID);

                // Update parent directory index
                foreach (FileNameRecord fileNameRecord in fileNameRecords)
                {
                    parentDirectoryIndex.AddEntry(fileRecord.BaseSegmentReference, fileNameRecord.GetBytes());
                }
                m_logClient.WriteForgetTransactionRecord(transactionID);
                m_logClient.WriteRestartRecord(true);
                return(fileRecord);
            }
        }
Beispiel #16
0
        public static List <FileNameRecord> GenerateFileNameRecords(MftSegmentReference parentDirectory, string fileName, bool isDirectory, bool generateDosName, IndexData parentDirectoryIndex, DateTime creationTime, DateTime modificationTime, DateTime mftModificationTime, DateTime lastAccessTime, ulong allocatedLength, ulong fileSize, FileAttributes fileAttributes, ushort packedEASize)
        {
            FileNameRecord fileNameRecord = new FileNameRecord(parentDirectory, fileName, isDirectory, creationTime);

            fileNameRecord.ParentDirectory     = parentDirectory;
            fileNameRecord.CreationTime        = creationTime;
            fileNameRecord.ModificationTime    = modificationTime;
            fileNameRecord.MftModificationTime = mftModificationTime;
            fileNameRecord.LastAccessTime      = lastAccessTime;
            fileNameRecord.AllocatedLength     = allocatedLength;
            fileNameRecord.FileSize            = fileSize;
            fileNameRecord.FileAttributes      = fileAttributes;
            fileNameRecord.PackedEASize        = packedEASize;
            fileNameRecord.IsDirectory         = isDirectory;
            fileNameRecord.FileName            = fileName;
            bool createDosOnlyRecord = false;

            if (generateDosName)
            {
                fileNameRecord.Flags = FileNameFlags.Win32;
                if (DosFileNameHelper.IsValidDosFileName(fileName))
                {
                    fileNameRecord.Flags |= FileNameFlags.DOS;
                }
                else
                {
                    createDosOnlyRecord = true;
                }
            }
            else
            {
                // This is similar to Windows 8.1, When FileNameFlags.Win32 is set, Windows Server 2003's CHKDSK expects to find a record with FileNameFlags.DOS set.
                fileNameRecord.Flags = FileNameFlags.POSIX;
            }

            List <FileNameRecord> result = new List <FileNameRecord>();

            result.Add(fileNameRecord);
            if (createDosOnlyRecord)
            {
                string         dosFileName   = DosFileNameHelper.GenerateDosName(parentDirectoryIndex, fileName);
                FileNameRecord dosOnlyRecord = new FileNameRecord(parentDirectory, dosFileName, isDirectory, creationTime);
                dosOnlyRecord.Flags = FileNameFlags.DOS;
                result.Add(dosOnlyRecord);
            }

            return(result);
        }
Beispiel #17
0
        public static List <FileNameRecord> GenerateFileNameRecords(MftSegmentReference parentDirectory, string fileName, bool isDirectory, bool generateDosName, IndexData parentDirectoryIndex)
        {
            DateTime creationTime = DateTime.Now;

            return(GenerateFileNameRecords(parentDirectory, fileName, isDirectory, generateDosName, parentDirectoryIndex, creationTime, creationTime, creationTime, creationTime, 0, 0, 0, 0));
        }
Beispiel #18
0
        public virtual void MoveFile(FileRecord fileRecord, MftSegmentReference newParentDirectory, string newFileName)
        {
            // Worst case scenrario: the new parent directory index requires multiple splits.
            // We assume IndexData.ExtendGranularity is bigger than or equal to the number of splits.
            if (NumberOfFreeClusters < NumberOfClustersRequiredToExtendIndex)
            {
                throw new DiskFullException();
            }

            lock (m_mftLock)
            {
                FileRecord oldParentDirectoryRecord = GetFileRecord(fileRecord.ParentDirectoryReference);
                IndexData  oldParentDirectoryIndex  = new IndexData(this, oldParentDirectoryRecord, AttributeType.FileName);
                IndexData  newParentDirectoryIndex;
                if (fileRecord.ParentDirectoryReference == newParentDirectory)
                {
                    newParentDirectoryIndex = oldParentDirectoryIndex;
                }
                else
                {
                    FileRecord newParentDirectoryRecord = GetFileRecord(newParentDirectory);
                    newParentDirectoryIndex = new IndexData(this, newParentDirectoryRecord, AttributeType.FileName);
                }

                if (newParentDirectoryIndex.ContainsFileName(newFileName))
                {
                    throw new AlreadyExistsException();
                }

                List <FileNameRecord> fileNameRecords = fileRecord.FileNameRecords;
                uint transactionID = m_logClient.AllocateTransactionID();
                foreach (FileNameRecord fileNameRecord in fileNameRecords)
                {
                    oldParentDirectoryIndex.RemoveEntry(fileNameRecord.GetBytes());
                }

                // Windows will not update the dates and FileAttributes in $File_Name as often as their counterparts in $STANDARD_INFORMATION.
                DateTime       creationTime        = fileRecord.StandardInformation.CreationTime;
                DateTime       modificationTime    = fileRecord.StandardInformation.ModificationTime;
                DateTime       mftModificationTime = fileRecord.StandardInformation.MftModificationTime;
                DateTime       lastAccessTime      = fileRecord.StandardInformation.LastAccessTime;
                ulong          allocatedLength     = fileRecord.FileNameRecord.AllocatedLength;
                FileAttributes fileAttributes      = fileRecord.StandardInformation.FileAttributes;
                ushort         packedEASize        = fileRecord.FileNameRecord.PackedEASize;
                // Windows NTFS v5.1 driver does not usually update the value of the FileSize field belonging to the FileNameRecords that are stored in the FileRecord.
                // The driver does update the value during a rename, which is inconsistent file creation and is likely to be incidental rather than intentional.
                // We will set the value to 0 to be consistent with file creation.
                fileNameRecords = IndexHelper.GenerateFileNameRecords(newParentDirectory, newFileName, fileRecord.IsDirectory, GenerateDosNames, newParentDirectoryIndex, creationTime, modificationTime, mftModificationTime, lastAccessTime, allocatedLength, 0, fileAttributes, packedEASize);
                fileRecord.RemoveAttributeRecords(AttributeType.FileName, String.Empty);
                foreach (FileNameRecord fileNameRecord in fileNameRecords)
                {
                    FileNameAttributeRecord fileNameAttribute = (FileNameAttributeRecord)fileRecord.CreateAttributeRecord(AttributeType.FileName, String.Empty);
                    fileNameAttribute.IsIndexed = true;
                    fileNameAttribute.Record    = fileNameRecord;
                }
                UpdateFileRecord(fileRecord, transactionID);

                foreach (FileNameRecord fileNameRecord in fileNameRecords)
                {
                    if (!fileRecord.IsDirectory)
                    {
                        fileNameRecord.FileSize = fileRecord.DataRecord.DataLength;
                    }
                    newParentDirectoryIndex.AddEntry(fileRecord.BaseSegmentReference, fileNameRecord.GetBytes());
                }
                m_logClient.WriteForgetTransactionRecord(transactionID);
                m_logClient.WriteRestartRecord(true);
            }
        }