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; } } }
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); } }
//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; } } }