public void printData(FileRecordSegmentHeader folder, string name) { foreach (var node in ((IndexRoot)folder.attributes.ElementAt(2)).Children) { if (((FileName)node.attributes.ElementAt(1)).Filename.Equals(name)) { Console.WriteLine(); Console.WriteLine("About the MFT entry (STANDARD_INFORMATION + FILE_NAME + DATA):"); Console.WriteLine("Entry was created : {0}", ((StandardInformation)node.attributes.ElementAt(0)).CreationTime); Console.WriteLine("Entry was last modified : {0}", ((StandardInformation)node.attributes.ElementAt(0)).ModifiedTime); Console.WriteLine("Entry was last accessed : {0}", ((StandardInformation)node.attributes.ElementAt(0)).AccessTime); Console.WriteLine("MFT for Entry was last changed : {0}", ((StandardInformation)node.attributes.ElementAt(0)).MFTChangeTime); Console.WriteLine(); Console.WriteLine("About the DATA:"); Console.WriteLine("File was created : {0}", ((FileName)node.attributes.ElementAt(1)).CreationTime); Console.WriteLine("File was last modified : {0}", ((FileName)node.attributes.ElementAt(1)).ModifiedTime); Console.WriteLine("File was last accessed : {0}", ((FileName)node.attributes.ElementAt(1)).AccessTime); Console.WriteLine("MFT for file was last changed : {0}", ((FileName)node.attributes.ElementAt(1)).MFTChangeTime); Console.WriteLine("Real size : {0}", ((FileName)node.attributes.ElementAt(1)).RealSize); Console.WriteLine("Allocated size : {0}", ((FileName)node.attributes.ElementAt(1)).AllocatedSize); Console.WriteLine(); Console.WriteLine("Starting from the MFT header for this file (starting address is a local 0):"); Console.WriteLine("STANDARD_INFORMATION offset: 24B"); Console.WriteLine("FILE_NAME offset: {0}B", 24 + ((StandardInformation)node.attributes.ElementAt(0)).RecordLength); Console.WriteLine("DATA offset: {0}B", 24 + ((StandardInformation)node.attributes.ElementAt(0)).RecordLength + ((FileName)node.attributes.ElementAt(1)).RecordLength); Console.WriteLine(); break; } } }
public void CreateFileRecordHeader(MFTEntryFlags flag, FileRecordSegmentHeader parent) { MSH = new MultiSectorHeader(); FirstAttributeOffset = 42; Flags = flag; if (Flags == MFTEntryFlags.FileRecordSegmentInUse) { TotalEntrySize = 64_000; UsedFolderSize = AllocatedFolderSize = 0; } else { UsedEntrySize = TotalEntrySize = 0; // UsedEntrySize for folders is size of the Stndfile + FileName file + IndexRoot file if (parent == null) // root folder { this.parent = null; } else { this.parent = parent; } } UsedEntrySize = 42; }
private void CreateRoot(string name) { Root = new FileRecordSegmentHeader(); Root.CreateFileRecordHeader(Enums.MFTEntryFlags.FileNameIndexPresent, null); StandardInformation stdInfo = new StandardInformation(); stdInfo.CreateStandInfoFile(FileAttributes.Normal); Root.UsedEntrySize += stdInfo.RecordLength; IndexRoot indRoot = new IndexRoot(); //Root.UsedEntrySize += (uint)indRoot.numberOfChildren * 8; // reference is 8 B FileName fileName = new FileName(); fileName.CreateFileNameFile(name); fileName.RealSize = fileName.AllocatedSize = 0; Root.UsedEntrySize += fileName.RecordLength; Root.attributes.Add(stdInfo); Root.attributes.Add(fileName); Root.attributes.Add(indRoot); BytesOccupied += Root.UsedEntrySize; }
public void changeName(FileRecordSegmentHeader folder, string oldName, string newName) { foreach (var node in ((IndexRoot)folder.attributes.ElementAt(2)).Children) { if (((FileName)node.attributes.ElementAt(1)).Filename.Equals(oldName)) { if ((newName.Length > oldName.Length && (node.TotalEntrySize - node.UsedEntrySize) > newName.Length) || newName.Length <= oldName.Length) { node.UsedEntrySize += (uint)(newName.Length - oldName.Length); string theName; if (node.attributes.ElementAt(2) is Data) { string[] split = ((FileName)node.attributes.ElementAt(1)).Filename.Split('.'); split[0] = newName; theName = split[0] + "." + split[1]; } else { theName = newName; } FileName fn = new FileName(); fn.CreateFileNameFile(theName); fn.CreationTime = ((FileName)node.attributes.ElementAt(1)).CreationTime; fn.AllocatedSize = ((FileName)node.attributes.ElementAt(1)).AllocatedSize; fn.RealSize = ((FileName)node.attributes.ElementAt(1)).RealSize; node.attributes[1] = fn; } break; } } }
public FileRecordSegmentHeader FindFolder(FileRecordSegmentHeader folder, string searchDir) { foreach (var child in ((IndexRoot)folder.attributes.ElementAt(2)).Children) { if (((FileName)child.attributes.ElementAt(1)).Filename.Equals(searchDir)) { return(child); } } return(null); }
public byte[] searchDataInDirectory(FileRecordSegmentHeader dir, string name) { foreach (var child in ((IndexRoot)dir.attributes.ElementAt(2)).Children) { if (((FileName)child.attributes.ElementAt(1)).Filename.Equals(name)) { return(((Data)child.attributes.ElementAt(2)).DataBytes); } } return(null); }
public IEnumerable <FileRecordSegmentHeader> GetRecord() { while (true) { FileRecordSegmentHeader record = ReadNextRecord(); if (record == null) { break; } yield return(record); } }
static void CreateFile(FileRecordSegmentHeader parentFolder, FileRecordSegmentHeader childFile, string name, NtfsFileSystem fs) { childFile.CreateFileRecordHeader(Enums.MFTEntryFlags.FileRecordSegmentInUse, parentFolder); StandardInformation stdInfo = new StandardInformation(); stdInfo.CreateStandInfoFile(FileAttributes.Normal); childFile.UsedEntrySize += stdInfo.RecordLength; FileName fileName = new FileName(); fileName.CreateFileNameFile(name); childFile.UsedEntrySize += fileName.RecordLength; fileName.AllocatedSize = childFile.TotalEntrySize - childFile.UsedEntrySize; fileName.RealSize = 0; childFile.UsedEntrySize += (uint)fileName.RealSize; Data data = new Data(); childFile.attributes.Add(stdInfo); childFile.attributes.Add(fileName); childFile.attributes.Add(data); if (childFile.TotalEntrySize < (fs.VolumeSize - fs.BytesOccupied) + 8) // +8 for reference in folder { fs.mftHeaderRecord.Add(childFile); ((FileSystem.Attributes.Indexroot.IndexRoot)parentFolder.attributes.ElementAt(2)).Children.Add(childFile); ((FileSystem.Attributes.Indexroot.IndexRoot)parentFolder.attributes.ElementAt(2)).numberOfChildren++; childFile.parent = parentFolder; fs.FileRecordCount++; fs.BytesOccupied += 8; // one child added fs.BytesOccupied += childFile.TotalEntrySize; parentFolder.UsedFolderSize += childFile.TotalEntrySize; } else { Console.WriteLine("Volume is full!"); Save(fs.VolName.Name, fs.Save()); Environment.Exit(0); } }
public static FileRecordSegmentHeader ReadFileRecord(byte[] data, int offset, ushort bytesPerSector, uint sectors) { uint length = bytesPerSector * sectors; if (data.Length - offset < length || length < 50 || !(bytesPerSector % 512 == 0 && bytesPerSector > 0) || sectors < 0) { throw new Exception("Error in parsing the 'FILE_RECORD_SEGMENT_HEADER'!\n"); } FileRecordSegmentHeader record = new FileRecordSegmentHeader(); // offset size record.MSH = new MultiSectorHeader(data, offset); // 0 4+2+2=8 record.LSN = BitConverter.ToUInt64(data, offset + 8); // 8 8 record.SequenceNumber = BitConverter.ToUInt16(data, offset + 16); // 16 2 record.ReferenceLinkCount = BitConverter.ToInt16(data, offset + 18); // 18 2 record.FirstAttributeOffset = BitConverter.ToUInt16(data, offset + 20); // 20 2 record.Flags = (MFTEntryFlags)BitConverter.ToUInt16(data, offset + 22); // 22 2 record.UsedEntrySize = BitConverter.ToUInt32(data, offset + 24); // 24 4 record.TotalEntrySize = BitConverter.ToUInt32(data, offset + 32); // 28 4 record.BaseFileRecordSegment = new MFTSegmentReference(BitConverter.ToUInt64(data, offset + 32)); // 32 8 record.FirstNextFreeAttributeId = BitConverter.ToUInt16(data, offset + 40); // 40 2 // Used to align to 4-byte boundary (only since NTFS version 3.1) [offset : 0x2A] // 42 2 record.MFTNumber = BitConverter.ToUInt16(data, offset + 44); // 44 4 record.UpdateSequenceArray = new byte[2]; Array.Copy(data, offset + record.MSH.UpdateSequenceArrayOffset, record.UpdateSequenceArray, 0, 2); record.SequenceArray = new byte[record.MSH.SequenceArraySize * 2 - 2]; Array.Copy(data, offset + record.MSH.UpdateSequenceArrayOffset + 2, record.SequenceArray, 0, record.SequenceArray.Length); record.MftSegmentReference = new MFTSegmentReference(record.MFTNumber, record.SequenceNumber); NtfsHelper.ApplyUpdateSequenceNumberPatch(data, offset, sectors, bytesPerSector, record.UpdateSequenceArray, record.SequenceArray); record.attributes = new List <AttributeRecord>(); //record.externalAttributes = new List<AttributeRecord>(); record.ReadAttributes(data, record.UsedEntrySize - record.FirstAttributeOffset, offset + record.FirstAttributeOffset); return(record); }
//private void ReadBoot() //{ // byte[] data = new byte[512]; // diskStream.Seek(0, SeekOrigin.Begin); // diskStream.Read(data, 0, data.Length); // boot = BootSector.DataReader(data, data.Length, 0); // parsing boot // BytesPerFileRecord = boot.ExtenedBPB.ClustersPerMFTRecord; // sectorsPerRecord = boot.ExtenedBPB.ClustersPerMFTRecord / boot.BIOSParameterBlock.BytesPerSector; //} //private void ReadMFT() //{ // buffer = new byte[BytesPerFileRecord]; // diskStream.Seek((long)(boot.ExtenedBPB.MFTClusterNumber * BytesPerCluster), SeekOrigin.Begin); // diskStream.Read(buffer, 0, buffer.Length); // FileRecordSegmentHeader record = FileRecordSegmentHeader.ReadFileRecord(buffer, 0, boot.BIOSParameterBlock.BytesPerSector, sectorsPerRecord); // mftHeaderRecord = record; // // mftStream = new NtfsDiskStream(diskStream, BytesPerCluster); // CurrentMftRecordNumber = 0; // FileRecordCount = (uint)(mftStream.Length / BytesPerFileRecord); //} public FileRecordSegmentHeader ReadNextRecord() { uint newPosition = CurrentMftRecordNumber * BytesPerFileRecord; if (mftStream.Position != newPosition) { mftStream.Seek(newPosition, SeekOrigin.Begin); } if (mftStream.Read(buffer, 0, buffer.Length) == 0) { return(null); } FileRecordSegmentHeader record = FileRecordSegmentHeader.ReadFileRecord(buffer, 0, boot.BIOSParameterBlock.BytesPerSector, sectorsPerRecord); CurrentMftRecordNumber = record.MFTNumber + 1; return(record); }
//static void MessageWrite(string str) //{ // Console.Write(">" + "{0} {1}\n>", str, message1); // Console.ReadLine(); //} static void CreateDirectory(FileRecordSegmentHeader parentFolder, FileRecordSegmentHeader childFolder, string name, NtfsFileSystem fs) { childFolder.CreateFileRecordHeader(Enums.MFTEntryFlags.FileNameIndexPresent, parentFolder); StandardInformation stdInfo = new StandardInformation(); stdInfo.CreateStandInfoFile(FileAttributes.Normal); childFolder.UsedEntrySize += stdInfo.RecordLength; IndexRoot indRoot = new IndexRoot(); //childFolder.UsedEntrySize += indRoot.RecordLength; FileName fileName = new FileName(); fileName.CreateFileNameFile(name); fileName.RealSize = fileName.AllocatedSize = 0; childFolder.UsedEntrySize += fileName.RecordLength; if (childFolder.UsedEntrySize >= (fs.VolumeSize - fs.BytesOccupied + 8)) { Console.WriteLine("Volume is full!"); Save(fs.VolName.Name, fs.Save()); Environment.Exit(0); } childFolder.attributes.Add(stdInfo); childFolder.attributes.Add(fileName); childFolder.attributes.Add(indRoot); ((IndexRoot)parentFolder.attributes.ElementAt(2)).Children.Add(childFolder); ((IndexRoot)parentFolder.attributes.ElementAt(2)).numberOfChildren++; childFolder.parent = parentFolder; fs.BytesOccupied += childFolder.UsedEntrySize + 8; fs.DirectoryRecordCount++; parentFolder.UsedFolderSize += childFolder.UsedEntrySize; }
static void Main(string[] args) { string command, fsName, subDir1, subDir2, currentDir; subDir1 = subDir2 = string.Empty; while (true) { Console.Clear(); Console.Write(">" + "Enter Filesystem name!\n>"); command = Console.ReadLine(); //command.Substring(command.IndexOf(">")); if (Regex.IsMatch(command, @"^[A-Za-z0-9]+$")) { fsName = command; break; } else { Console.Write(">" + "FS name is not valid!" + message1); Console.ReadLine(); } } NtfsFileSystem ntfsFS = new NtfsFileSystem(fsName); currentDir = fsName; var currectFolder = ntfsFS.Root; Console.Clear(); while (true) { Console.Write("{0}:\\{1}{2}>", fsName, subDir1 == string.Empty ? subDir1 : subDir1 + "\\", subDir2); string[] textCatch = Console.ReadLine().Split('"'); // e.q. textCatch[1] is "text for input." string[] tokens = (textCatch[0].ToLower()).Split(' '); //string[] tokens = command.Split(' '); command = tokens[0]; command = command.Trim(); bool toContinue = true; choice selected = choice.wrong_command; { int i = 0; foreach (var ch in choices) { if (command.Equals(choices[i++].Item1)) { selected = (choice)(--i); } if (ch.Item1.Equals(command) && (tokens.Length - 1 >= ch.Item2 && tokens.Length - 1 <= ch.Item3)) { toContinue = false; break; } } } if (toContinue) { Console.Write("{0}:\\>{1} {2}\n", fsName, "Command has wrong number of arguments!", message1); //Console.ReadLine(); continue; } //for (int i = 0; i < (int)choice.cd_remove; ++i) // if (command.Equals(choices[i].Item1)) // { // selected = (choice)i; // break; // } if (selected != choice.wrong_command) { switch (selected) { case choice.mkdir: { if (!(subDir1 != String.Empty && subDir2 != String.Empty)) { FileRecordSegmentHeader mkFolder = new FileRecordSegmentHeader(); CreateDirectory(currectFolder, mkFolder, tokens[1], ntfsFS); } else { Console.WriteLine("Allowed directory depth is 2. Can't make {0} directory!", tokens[1]); } break; } case choice.create: { FileRecordSegmentHeader createFile = new FileRecordSegmentHeader(); CreateFile(currectFolder, createFile, tokens[1], ntfsFS); break; } case choice.put: { //if (Directory.Exists(tokens[1])) using (var stream = new FileStream(tokens[1], FileMode.Open)) { if (stream.Length <= 64_000) { try { FileRecordSegmentHeader header = new FileRecordSegmentHeader(); FileRecordSegmentHeader parent = currectFolder; header.CreateFileRecordHeader(Enums.MFTEntryFlags.FileRecordSegmentInUse, parent); StandardInformation stdInfo = new StandardInformation(); stdInfo.CreateStandInfoFile(FileAttributes.Normal); header.UsedEntrySize += stdInfo.RecordLength; FileName fileName = new FileName(); fileName.CreateFileNameFile(Path.GetFileName(tokens[1])); header.UsedEntrySize += fileName.RecordLength; if (stream.Length <= (header.TotalEntrySize - header.UsedEntrySize)) { fileName.AllocatedSize = header.TotalEntrySize - header.UsedEntrySize; fileName.RealSize = (ulong)stream.Length; header.UsedEntrySize += (uint)fileName.RealSize; Data data = new Data(); var mem = new MemoryStream(); stream.CopyTo(mem); data.DataBytes = mem.ToArray(); header.attributes.Add(stdInfo); header.attributes.Add(fileName); header.attributes.Add(data); if (header.TotalEntrySize < (ntfsFS.VolumeSize - ntfsFS.BytesOccupied) + 8) // +8 for reference in folder { ntfsFS.mftHeaderRecord.Add(header); ((FileSystem.Attributes.Indexroot.IndexRoot)parent.attributes.ElementAt(2)).Children.Add(header); ((FileSystem.Attributes.Indexroot.IndexRoot)parent.attributes.ElementAt(2)).numberOfChildren++; header.parent = parent; ntfsFS.FileRecordCount++; ntfsFS.BytesOccupied += 8; // one child added ntfsFS.BytesOccupied += header.TotalEntrySize; parent.UsedFolderSize += header.TotalEntrySize; } else { Save(fsName, ntfsFS.Save()); throw new Exception("Volume is full!"); } } else { Console.WriteLine("File is too large!"); } } catch (Exception e) { Console.WriteLine(e); Environment.Exit(0); } } else { Console.WriteLine("File is larger than 64 KB!"); } } //else // Console.WriteLine("Directory '{0}' doesn't exist!", tokens[1]); break; } case choice.get: { //FileInfo fileInfo = new FileInfo(tokens[1]); //using (FileStream fs = fileInfo.Create()) //{ byte[] data = ntfsFS.searchDataInDirectory(currectFolder, tokens[2]); if (data != null) { File.WriteAllBytes(tokens[1], data); } else { Console.WriteLine("File is not located in the current folder!"); } break; } case choice.ls: { Console.WriteLine(); foreach (var child in ((FileSystem.Attributes.Indexroot.IndexRoot)currectFolder.attributes.ElementAt(2)).Children) { if (child.Flags == Enums.MFTEntryFlags.FileRecordSegmentInUse) { Console.WriteLine(((StandardInformation)child.attributes.ElementAt(0)).CreationTime.ToString() + " " + " " + child.UsedEntrySize.ToString("N1") + " " + ((FileName)child.attributes.ElementAt(1)).Filename); } else { Console.WriteLine(((StandardInformation)child.attributes.ElementAt(0)).CreationTime.ToString() + " " + "<DIR>" + " " + ((FileName)child.attributes.ElementAt(1)).Filename); } } Console.WriteLine(); break; } case choice.cp: { try { // get the file FileRecordSegmentHeader fileToCpy = null; FileRecordSegmentHeader header = new FileRecordSegmentHeader(); FileRecordSegmentHeader parent = null; foreach (var child in ((FileSystem.Attributes.Indexroot.IndexRoot)currectFolder.attributes.ElementAt(2)).Children) { if (((FileName)child.attributes.ElementAt(1)).Filename.Equals(tokens[1])) { fileToCpy = child; break; } } if (fileToCpy != null) { string[] splitDestination = tokens[2].Split('\\'); if (splitDestination.Length > 2) { Console.WriteLine("Moving failed!"); } else { FileRecordSegmentHeader moveFolder = null; FileRecordSegmentHeader tmp = null; foreach (var child in ((FileSystem.Attributes.Indexroot.IndexRoot)currectFolder.parent.attributes.ElementAt(2)).Children) { if (((FileName)child.attributes.ElementAt(1)).Filename.Equals(splitDestination[0])) { tmp = moveFolder = child; break; } } if (moveFolder != null) { if (splitDestination.Length == 2) { foreach (var child in ((FileSystem.Attributes.Indexroot.IndexRoot)tmp.attributes.ElementAt(2)).Children) { if (((FileName)child.attributes.ElementAt(1)).Filename.Equals(splitDestination[1])) { moveFolder = child; break; } } if ((tmp != moveFolder && splitDestination.Length == 2) || (tmp == moveFolder && splitDestination.Length == 1)) { //((FileSystem.Attributes.Indexroot.IndexRoot)currectFolder.attributes.ElementAt(2)).Children.Remove(moveFolder); //((FileSystem.Attributes.Indexroot.IndexRoot)moveFolder.attributes.ElementAt(2)).Children.Add(moveFolder); //moveFolder.parent = moveFolder; parent = moveFolder; header.CreateFileRecordHeader(Enums.MFTEntryFlags.FileRecordSegmentInUse, parent); StandardInformation stdInfo = new StandardInformation(); stdInfo.CreateStandInfoFile(FileAttributes.Normal); header.UsedEntrySize += stdInfo.RecordLength; FileName fileName = new FileName(); fileName.CreateFileNameFile(((FileName)fileToCpy.attributes.ElementAt(1)).Filename); header.UsedEntrySize += fileName.RecordLength; fileName.AllocatedSize = header.TotalEntrySize - header.UsedEntrySize; fileName.RealSize = (ulong)((FileName)fileToCpy.attributes.ElementAt(1)).RealSize; header.UsedEntrySize += (uint)fileName.RealSize; Data data = new Data(); Array.Copy(((Data)fileToCpy.attributes.ElementAt(2)).DataBytes, 0, data.DataBytes, 0, ((Data)fileToCpy.attributes.ElementAt(2)).DataBytes.Length); header.attributes.Add(stdInfo); header.attributes.Add(fileName); header.attributes.Add(data); if (header.TotalEntrySize < (ntfsFS.VolumeSize - ntfsFS.BytesOccupied) + 8) // +8 for reference in folder { ntfsFS.mftHeaderRecord.Add(header); ((FileSystem.Attributes.Indexroot.IndexRoot)parent.attributes.ElementAt(2)).Children.Add(header); ((FileSystem.Attributes.Indexroot.IndexRoot)parent.attributes.ElementAt(2)).numberOfChildren++; header.parent = parent; ntfsFS.FileRecordCount++; ntfsFS.BytesOccupied += 8; // one child added ntfsFS.BytesOccupied += header.TotalEntrySize; parent.UsedFolderSize += header.TotalEntrySize; } else { Save(fsName, ntfsFS.Save()); throw new Exception("Volume is full!"); } } else if (tmp == moveFolder && splitDestination.Length == 2) { Console.WriteLine("Copying failed!"); } } } else { Console.WriteLine("Copying failed!"); } } } else { Console.WriteLine("Copying failed!"); } } catch (Exception e) { Console.WriteLine(e); Environment.Exit(0); } break; } case choice.mv: { string[] splitDestination = tokens[2].Split('\\'); if (splitDestination.Length > 2) { Console.WriteLine("Moving failed!"); } else { FileRecordSegmentHeader movingFile = null; foreach (var child in ((FileSystem.Attributes.Indexroot.IndexRoot)currectFolder.attributes.ElementAt(2)).Children) { if (((FileName)child.attributes.ElementAt(1)).Filename.Equals(tokens[1])) { movingFile = child; break; } } if (movingFile != null) { FileRecordSegmentHeader moveFolder = null; FileRecordSegmentHeader tmp = null; foreach (var child in ((FileSystem.Attributes.Indexroot.IndexRoot)currectFolder.parent.attributes.ElementAt(2)).Children) { if (((FileName)child.attributes.ElementAt(1)).Filename.Equals(splitDestination[0])) { tmp = moveFolder = child; break; } } if (moveFolder != null) { if (splitDestination.Length == 2) { foreach (var child in ((FileSystem.Attributes.Indexroot.IndexRoot)tmp.attributes.ElementAt(2)).Children) { if (((FileName)child.attributes.ElementAt(1)).Filename.Equals(splitDestination[1])) { moveFolder = child; break; } } } if ((tmp != moveFolder && splitDestination.Length == 2) || (tmp == moveFolder && splitDestination.Length == 1)) { ((FileSystem.Attributes.Indexroot.IndexRoot)currectFolder.attributes.ElementAt(2)).Children.Remove(movingFile); ((FileSystem.Attributes.Indexroot.IndexRoot)moveFolder.attributes.ElementAt(2)).Children.Add(movingFile); moveFolder.parent = moveFolder; } else if (tmp == moveFolder && splitDestination.Length == 2) { Console.WriteLine("Moving failed!"); } } else { Console.WriteLine("Moving failed!"); } } else { Console.WriteLine("Moving failed!"); } } break; } case choice.rename: { ntfsFS.changeName(currectFolder, tokens[1], tokens[2]); break; } case choice.echo: { try { if (textCatch[1].Length < 64_000) { FileRecordSegmentHeader header = new FileRecordSegmentHeader(); FileRecordSegmentHeader parent = currectFolder; header.CreateFileRecordHeader(Enums.MFTEntryFlags.FileRecordSegmentInUse, parent); StandardInformation stdInfo = new StandardInformation(); stdInfo.CreateStandInfoFile(FileAttributes.Normal); header.UsedEntrySize += stdInfo.RecordLength; FileName fileName = new FileName(); fileName.CreateFileNameFile(tokens[1]); header.UsedEntrySize += fileName.RecordLength; if (textCatch.Length <= (header.TotalEntrySize - header.UsedEntrySize)) { fileName.AllocatedSize = header.TotalEntrySize - header.UsedEntrySize; fileName.RealSize = (ulong)textCatch.Length; header.UsedEntrySize += (uint)fileName.RealSize; Data data = new Data(); //Array.Copy(textCatch, 0, data.DataBytes, 0, textCatch.Length); data.DataBytes = Encoding.ASCII.GetBytes(textCatch[1]); header.attributes.Add(stdInfo); header.attributes.Add(fileName); header.attributes.Add(data); if (header.TotalEntrySize < (ntfsFS.VolumeSize - ntfsFS.BytesOccupied) + 8) // +8 for reference in folder { ntfsFS.mftHeaderRecord.Add(header); ((FileSystem.Attributes.Indexroot.IndexRoot)parent.attributes.ElementAt(2)).Children.Add(header); ((FileSystem.Attributes.Indexroot.IndexRoot)parent.attributes.ElementAt(2)).numberOfChildren++; header.parent = parent; ntfsFS.FileRecordCount++; ntfsFS.BytesOccupied += 8; // one child added ntfsFS.BytesOccupied += header.TotalEntrySize; parent.UsedFolderSize += header.TotalEntrySize; } else { Save(fsName, ntfsFS.Save()); throw new Exception("Volume is full!"); } } else { Console.WriteLine("File is too large!"); } } else { Console.WriteLine("Text file is larger than 64 KB!"); } } catch (Exception e) { Console.WriteLine(e); Environment.Exit(0); } break; } case choice.cat: { if (tokens[1].Contains(".txt")) { Console.WriteLine(System.Text.Encoding.ASCII.GetString(ntfsFS.searchDataInDirectory(currectFolder, tokens[1]))); } else { Console.WriteLine("File is not *.txt!"); } break; } case choice.rm: { FileRecordSegmentHeader deleteThisChild = null; foreach (var child in ((IndexRoot)currectFolder.attributes.ElementAt(2)).Children) { if (((FileName)child.attributes.ElementAt(1)).Filename.Equals(tokens[1])) { deleteThisChild = child; break; } } if (deleteThisChild != null) { ntfsFS.BytesOccupied -= 8; ntfsFS.BytesOccupied -= deleteThisChild.TotalEntrySize; currectFolder.UsedFolderSize = deleteThisChild.TotalEntrySize; if (deleteThisChild.Flags == Enums.MFTEntryFlags.FileRecordSegmentInUse) { ntfsFS.FileRecordCount--; } else { ntfsFS.DirectoryRecordCount--; } ((IndexRoot)currectFolder.attributes.ElementAt(2)).Children.Remove(deleteThisChild); deleteThisChild.parent = null; } else { Console.WriteLine("File/Folder not found!"); } break; } case choice.stat: { ntfsFS.printData(currectFolder, tokens[1]); break; } case choice.cd: { if (!currentDir.Equals(tokens[1])) { var currectFolderNew = ntfsFS.FindFolder(currectFolder, tokens[1]); if (currectFolderNew != null) { currectFolder = currectFolderNew; if (currentDir.Equals(fsName)) { currentDir = subDir1 = tokens[1]; } else if (currentDir.Equals(subDir1)) { currentDir = subDir2 = tokens[1]; } } else { Console.WriteLine("Directory '{0}' doesn't exist in '{1}'!", tokens[1], currentDir); } } else { Console.WriteLine("This is not possible!"); } break; } case choice.cd_remove: { if (currentDir == fsName) { // Save NtfsFileSystem to *.dat file Save(fsName, ntfsFS.Save()); currentDir = string.Empty; Environment.Exit(0); } else if (subDir2 != string.Empty) { var parentFolder = currectFolder.parent; currectFolder = parentFolder; subDir2 = string.Empty; currentDir = subDir1; } else { currectFolder = ntfsFS.Root; subDir1 = string.Empty; currentDir = fsName; } break; } case choice.cls: { Console.Clear(); break; } case choice.exit: { Save(fsName, ntfsFS.Save()); Environment.Exit(0); break; } } } else { Console.Write("{0}:\\>{1} {2}\n", fsName, "Unknown command.", message1); continue; } } }