public void ExpandFile(long TotalLength) { // If the total size is larger than uint32.maxvalue... if (TotalLength > UInt32.MaxValue) { throw new Exception("Filesize too large!"); } // We'll be adding clusters here, so first thing we need to do is figure out // how many clusters we need long Difference = TotalLength - Size; // Now that we have the difference, let's see if we don't have to allocate // any more clusters if (Size.UpToNearestCluster(PartitionInfo.ClusterSize) == TotalLength.UpToNearestCluster(PartitionInfo.ClusterSize)) { // We don't have to do anything except write the new size! Yay Structs.EntryData newEd = EntryData; newEd.Size = (uint)TotalLength; new EntryFunctions(this).CreateNewEntry(newEd); EntryData = newEd; return; } // Looks like we'll be adding clusters... else if (Size.UpToNearestCluster(PartitionInfo.ClusterSize) > TotalLength.UpToNearestCluster(PartitionInfo.ClusterSize) || (Size == 0)) { int ClustersToAdd = (int)(TotalLength.UpToNearestCluster(PartitionInfo.ClusterSize) / PartitionInfo.ClusterSize); // Subtract the total clusters from the number clusters we already have ClustersToAdd -= BlocksOccupied.Length; // Get the new clusters! uint[] FreeClusters = Drive.GetFreeBlocks(Drive.FolderFromPath(FullPath.Remove(FullPath.IndexOf("\\"))), ClustersToAdd, 1, 0, false); // Add those to our current chain List<uint> Current = BlocksOccupied.ToList(); Current.AddRange(FreeClusters); EntryFunctions ef = new EntryFunctions(this); // Write the cluster chain ef.WriteFATChain(Current.ToArray()); // Subtract some of the space remaining on the drive if (Drive.Remaining != ~0UL) { Drive.Remaining -= (ulong)(ClustersToAdd * PartitionInfo.ClusterSize); } // Replace the currently loaded clusters in the file BlocksOccupied = Current.ToArray(); // Overwrite the size in the entry data Structs.EntryData ed = EntryData; ed.Size = (uint)TotalLength; if (Size == 0) { ed.StartingCluster = Current[0]; } // Write the new entry data ef.CreateNewEntry(ed); EntryData = ed; return; } // TotalLength might be smaller, throw an exception throw new Exception("Can not shrink file!"); }
public void TruncateFile(long TotalLength) { if (TotalLength < 0) { throw new Exception("File size must be non-negative number"); } if (Size == 0) { return; } long Difference = Size - TotalLength; if (VariousFunctions.DownToNearestCluster(Difference, PartitionInfo.ClusterSize) != VariousFunctions.DownToNearestCluster(Size, PartitionInfo.ClusterSize)) { // Looks like we have to remove part of the cluster chain... if (TotalLength == 0) { new EntryFunctions(this).ClearFATChain(this.BlocksOccupied); this.BlocksOccupied = new uint[0]; } else { List<uint> Chain = this.BlocksOccupied.ToList(); // Number of clusters to remove int ClustersToRemove = Chain.Count - (int)((TotalLength > PartitionInfo.ClusterSize) ? 1 : (VariousFunctions.UpToNearestCluster(TotalLength, PartitionInfo.ClusterSize) / PartitionInfo.ClusterSize)); EntryFunctions ef = new EntryFunctions(this); // Clear the cluster chain ef.ClearFATChain(Chain.ToArray()); Chain.RemoveRange((int)((TotalLength > PartitionInfo.ClusterSize) ? 1 : (VariousFunctions.UpToNearestCluster(TotalLength, PartitionInfo.ClusterSize) / PartitionInfo.ClusterSize)), ClustersToRemove); // Re-write the cluster chain ef.WriteFATChain(Chain.ToArray()); BlocksOccupied = Chain.ToArray(); } } { EntryData newE = this.EntryData; newE.Size = (uint)TotalLength; if (TotalLength == 0) { newE.StartingCluster = 0; } EntryFunctions ef = new EntryFunctions(this); ef.CreateNewEntry(newE); this.EntryData = newE; } }
internal void UpdateModifiedTime() { if (this.EntryData.EntryOffset != 0) { EntryFunctions ef = new EntryFunctions(this); EntryData ed = this.EntryData; ed.ModifiedDate = VariousFunctions.DateTimeToFATShort(DateTime.Now, true); ed.ModifiedTime = VariousFunctions.DateTimeToFATShort(DateTime.Now, false); this.EntryData = ed; ef.CreateNewEntry(ed); } }
/// <summary> /// Deletes the file from the parent folder, clears the FAT chain, etc. /// </summary> public void Delete() { if (this.IsDeleted) { return; } // File action (event) Structs.FileAction fa = new FileAction(); fa.FullPath = this.FullPath; fa.MaxValue = 2; OnFileAction(ref fa); // Create the entry functions so we can clear the FAT chain EntryFunctions ef = new EntryFunctions(this); if (Size != 0) { // Get the FAT chain uint[] FatChain = this.BlocksOccupied; // Clear the FAT chain ef.ClearFATChain(FatChain); // Add to the remaining space on the drive if (Drive.Remaining != ~0UL) { Drive.Remaining += (ulong)(FatChain.Length * PartitionInfo.ClusterSize); } // Dispose of the FatChain FatChain = null; } // Change the progress fa.Progress = 1; OnFileAction(ref fa); // Get the new entry data that we're going to write EntryData ed = this.EntryData; // Mark it as deleted ed.NameSize = 0xE5; // "Create" a new entry (writing the old one with the size of 0xE5 ef.CreateNewEntry(ed); // Change progress fa.Progress = 2; OnFileAction(ref fa); // Reset the entry data this.EntryData = ed; // Other event EntryEventArgs eea = new EntryEventArgs(); eea.FullParentPath = Parent.FullPath; eea.ModifiedEntry = this; eea.ParentFolder = this.Parent; eea.Deleting = true; if (Parent != null) { Parent.cachedFiles.Remove(this); Parent.cachedDeletedFiles.Add(this); try { Parent.OnEntryEvent(ref eea); } catch { } } }
public void SetFlags(byte Flags) { CLKsFATXLib.Structs.EntryData ed = EntryData; ed.Flags = Flags; EntryFunctions ef = new EntryFunctions(this); ef.CreateNewEntry(ed); this.EntryData = ed; }
public void SetTimeStamp(System.DateTime MDate, System.DateTime CDate, System.DateTime ADate) { if (this.EntryData.EntryOffset != 0) { EntryFunctions ef = new EntryFunctions(this); EntryData ed = this.EntryData; ed.ModifiedDate = VariousFunctions.DateTimeToFATShort(MDate, true); ed.ModifiedTime = VariousFunctions.DateTimeToFATShort(MDate, false); ed.AccessDate = VariousFunctions.DateTimeToFATShort(ADate, true); ed.AccessTime = VariousFunctions.DateTimeToFATShort(ADate, false); ed.CreationDate = VariousFunctions.DateTimeToFATShort(CDate, true); ed.CreationTime = VariousFunctions.DateTimeToFATShort(CDate, false); this.EntryData = ed; ef.CreateNewEntry(ed); } }
public Structs.WriteResult Move(string Destination) { WriteResult Result = new WriteResult(); // Get the destination folder Folder D = Drive.FolderFromPath(Destination); if (D.FullPath == this.Parent.FullPath || D.FullPath.Contains(this.FullPath)) { Result.Entry = this; return Result; } for (int i = 0; i < D.Folders().Length; i++) { if (D.Folders()[i].Name.ToLower() == Name.ToLower()) { Result.CouldNotWrite = true; Result.Entry = D.Folders()[i]; Result.ConflictingEntryPath = Result.Entry.FullPath; Result.AttemptedEntryToMove = this; return Result; } } for (int i = 0; i < D.Files().Length; i++) { if (D.Files()[i].Name.ToLower() == Name.ToLower()) { Result.CouldNotWrite = true; Result.Entry = D.Files()[i]; Result.ConflictingEntryPath = Result.Entry.FullPath; Result.AttemptedEntryToMove = this; return Result; } } // Get the offset for a new folder in the destination EntryFunctions ef = new EntryFunctions(D); long Offset = ef.GetNewEntryOffset(D); EntryData f = this.EntryData; byte NameSize = this.EntryData.NameSize; // Mark this entry as deleted and write it f.NameSize = 0xE5; ef.CreateNewEntry(f); // Reset the size of that name... f.NameSize = NameSize; // Set the offset to that of the new folder f.EntryOffset = Offset; // Write the entry ef.CreateNewEntry(f); this.EntryData = f; if (f.EntryOffset >= VariousFunctions.GetBlockOffset(this.BlocksOccupied[BlocksOccupied.Length - 1], this) + this.PartitionInfo.ClusterSize) { List<uint> blocks = this.BlocksOccupied.ToList(); blocks.Add(VariousFunctions.GetBlockFromOffset(f.EntryOffset, this.PartitionInfo)); this.BlocksOccupied = blocks.ToArray(); } if (Parent != null) { if (!this.IsFolder) { Parent.cachedFiles.Remove((File)this); Parent.cachedDeletedFiles.Add((File)this); } else { Parent.cachedFolders.Remove((Folder)this); Parent.cachedDeletedFolders.Add((Folder)this); } } Structs.EntryEventArgs ea = new EntryEventArgs(); ea.Deleting = true; ea.FullParentPath = this.Parent.FullPath; ea.ModifiedEntry = this; ea.ParentFolder = this.Parent; if (Parent != null) { if (Parent.EntryEventNull) { if (this.IsFolder) { if (!((Folder)this).EntryEventNull) { ((Folder)this).OnEntryEvent(ref ea); } } } else { Parent.OnEntryEvent(ref ea); } } else if (this.IsFolder) { if (!((Folder)this).EntryEventNull) { ((Folder)this).OnEntryEvent(ref ea); } } this.Parent = D; this.FullPath = this.Parent.FullPath + "\\" + Name; Structs.EntryEventArgs MovedEA = new EntryEventArgs(); MovedEA.Deleting = false; MovedEA.FullParentPath = this.Parent.FullPath; MovedEA.ModifiedEntry = this; MovedEA.ParentFolder = this.Parent; if (Parent != null) { if (Parent.EntryEventNull) { if (this.IsFolder) { if (!((Folder)this).EntryEventNull) { ((Folder)this).OnEntryEvent(ref MovedEA); } } } else { Parent.OnEntryEvent(ref MovedEA); } if (!this.IsFolder) { Parent.cachedFiles.Add((File)this); } else { Parent.cachedFolders.Add((Folder)this); } } else if (this.IsFolder) { if (!((Folder)this).EntryEventNull) { ((Folder)this).OnEntryEvent(ref MovedEA); } } Result.Entry = this; return Result; }
// Returns true for good, false for bad public bool Rename(string NewName) { if (VariousFunctions.CheckFileName(NewName)) { if (Name.ToLower() != NewName.ToLower()) { foreach (Folder f in Parent.Folders()) { if (f.Name.ToLower() == NewName.ToLower() && !f.IsDeleted) { throw new Exception("A folder with the desired name already exists!"); } } foreach (File f in Parent.Files()) { if (f.Name.ToLower() == NewName.ToLower() && !f.IsDeleted) { throw new Exception("A file with the desired name already exists!"); } } } EntryData ed = this.EntryData; ed.Name = NewName; ed.NameSize = (byte)NewName.Length; this.EntryData = ed; EntryFunctions ef = new EntryFunctions(this); ef.CreateNewEntry(EntryData); // Change the path to match that of the new name this.FullPath = Parent.FullPath + "\\" + NewName; return true; } return false; }
public Folder[] Folders() { // If all of those guys are null, that means we have to re-load them. if (cachedFolders == null && cachedFiles == null && cachedDeletedFiles == null && cachedDeletedFolders == null) { object[] entries = new EntryFunctions(this).GetEntries(this); cachedFiles = (List<File>)entries[0]; cachedFolders = (List<Folder>)entries[1]; cachedDeletedFiles = (List<File>)entries[2]; cachedDeletedFolders = (List<Folder>)entries[3]; } if (ReturnDeletedEntries) { foreach (Folder f in cachedDeletedFolders) { f.ReturnDeletedEntries = this.ReturnDeletedEntries; } } if (ReturnDeletedEntries) { Folder[] list = new Folder[cachedFolders.Count + cachedDeletedFolders.Count]; Array.Copy(cachedFolders.ToArray(), 0, list, 0, cachedFolders.Count); Array.Copy(cachedDeletedFolders.ToArray(), 0, list, cachedFolders.Count, cachedDeletedFolders.Count); return list; } return cachedFolders.ToArray(); }
/// <summary> /// Deletes all files and subfolders contained in this, and the folder itself /// </summary> public void Delete() { /* We're setting return deleted entries to false because: * 1.) We're deleting these folders, so the property doesn't matter anyway * 2.) We don't want to delete a deleted folder * 3.) Pickles */ ReturnDeletedEntries = false; // Loop for each folder in this foreach (Folder f in Folders()) { // While we're looping, we want to check if the user wants // to cancel the current action. If they do, then we stop and return if (fa.Cancel) { fa.Cancel = false; return; } // Set the folder action event so we can update stuff f.FolderAction += new FolderActionChanged(f_FolderAction); if (!f.IsDeleted) { // Call to delete the folder f.Delete(); } } // Now, loop through each file foreach (File f in Files()) { // If they want us to cancel... if (fa.Cancel) { // Set the cancel to false, then return fa.Cancel = false; return; } // Set the file action so we can update stuff again f.FileAction +=new FileActionChanged(f_FileAction); if (!f.IsDeleted) { // Delete the file f.Delete(); } } // Update our progress fa.CurrentFile = this.Name; fa.CurrentFilePath = this.FullPath; fa.MaxValue = 2; fa.Progress = 0; OnFolderAction(ref fa); // Clear the FAT chain of this folder EntryFunctions ef = new EntryFunctions(this); ef.ClearFATChain(this.BlocksOccupied); // Increase the remaining size left on the drive if (Drive.Remaining != ~0UL) { Drive.Remaining += (ulong)(this.BlocksOccupied.Length * PartitionInfo.ClusterSize); } // Update our progress again fa.Progress = 1; OnFolderAction(ref fa); // Create a new instance of the entry data EntryData ed = this.EntryData; // Set the size to 0xE5 (mark for deletion) ed.NameSize = 0xE5; // Re-write the entry data ef.CreateNewEntry(ed); // Reset this guy's entry data this.EntryData = ed; // Update our progress fa.Progress = 2; OnFolderAction(ref fa); // Remove this folder from the parent's cached stuff if (this.Parent != null) { this.Parent.cachedFolders.Remove(this); this.Parent.cachedDeletedFolders.Add(this); } // Update the FINAL progress EntryEventArgs eea = new EntryEventArgs(); eea.FullParentPath = Parent.FullPath; eea.ModifiedEntry = this; eea.ParentFolder = this.Parent; eea.Deleting = true; if (this.Parent != null && !this.Parent.EntryEventNull) { Parent.OnEntryEvent(ref eea); } else if (!this.EntryEventNull) { this.OnEntryEvent(ref eea); } }
/// <summary> /// Creates a new folder /// </summary> /// <param name="Name">New folder name</param> /// <returns>The existing file or folder will be returned if applicable, otherwise returns null (no problems encountered)</returns> public Structs.WriteResult CreateNewFolder(string Name) { WriteResult Result = new WriteResult(); Folders(); Console.WriteLine("Getting folders... comparing names"); for (int i = 0; i < cachedFolders.Count; i++) { if (cachedFolders[i].Name.ToLower() == Name.ToLower()) { Result.CouldNotWrite = true; Result.Entry = cachedFolders[i]; Result.ConflictingEntryPath = Result.Entry.FullPath; return Result; } } Console.WriteLine("Getting files... comparing names"); for (int i = 0; i < cachedFiles.Count; i++) { if (cachedFiles[i].Name.ToLower() == Name.ToLower()) { Result.CouldNotWrite = true; Result.Entry = cachedFiles[i]; Result.ConflictingEntryPath = Result.Entry.FullPath; return Result; } } EntryFunctions ef = new EntryFunctions(this); Console.WriteLine("Creating new folder"); Folder f = new Folder(this.PartitionInfo, ef.GetNewEntry(this, 0, new Geometry.Flags[] { Geometry.Flags.Directory }, Name), this.Drive); // Check if the new folder was created on a new cluster if (f.EntryOffset >= VariousFunctions.GetBlockOffset(this.BlocksOccupied[BlocksOccupied.Length - 1], this) + this.PartitionInfo.ClusterSize) { List<uint> blocks = this.BlocksOccupied.ToList(); blocks.Add(VariousFunctions.GetBlockFromOffset(f.EntryOffset, this.PartitionInfo)); this.BlocksOccupied = blocks.ToArray(); } Console.WriteLine("Writing FAT chain"); ef.WriteFATChain(new uint[] { f.EntryData.StartingCluster }); f.FullPath = this.FullPath + "\\" + f.Name; f.Parent = this; Streams.Writer w = this.Drive.Writer(); w.BaseStream.Position = f.StartingOffset; byte[] FF = new byte[PartitionInfo.ClusterSize]; for (int i = 0; i < FF.Length; i++) { FF[i] = 0xFF; } Console.WriteLine("Writing FF"); w.Write(FF); //Console.WriteLine("Closing stream"); //w.Close(); this.cachedFolders.Add(f); EntryEventArgs eea = new EntryEventArgs(); eea.FullParentPath = FullPath; eea.ModifiedEntry = f; eea.ParentFolder = this; OnEntryEvent(ref eea); Console.WriteLine("Updating entry modified time"); UpdateModifiedTime(); Result.Entry = f; return Result; }
/// <summary> /// Creates a new file from the given path /// </summary> /// <param name="Path">Path to the file</param> /// <returns>Returns a WriteResult with a bool indicating whether or not there were problems writing the file. If true, then the Entry property will be the conflicting entry</returns> public Structs.WriteResult CreateNewFile(string Path) { // Check to see if the file they want to use is currently in use try { System.IO.FileStream fs = System.IO.File.Open(Path, System.IO.FileMode.Open); // Check file length if (fs.Length > UInt32.MaxValue) { throw new Exception("File size too large! Must be smaller than " + UInt32.MaxValue.ToString() + " bytes!"); } // File was good, continue fs.Close(); } catch (Exception x) { Console.WriteLine("Error occured when creating new file. File in use"); throw x; } if (fa.Cancel) { return new WriteResult() { CouldNotWrite = false, }; } System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); EntryEventArgs eea = new EntryEventArgs(); string NewName = System.IO.Path.GetFileName(Path); fa.CurrentFilePath = this.FullPath + "\\" + NewName; fa.CurrentFile = NewName; fa.MaxValue = 1; fa.Progress = 0; OnFolderAction(ref fa); WriteResult Return = new WriteResult(); Console.WriteLine("Comparing folder/file names"); foreach (Folder f in Folders()) { if (f.Name.ToLower() == NewName.ToLower()) { Return.Entry = f; Return.CouldNotWrite = true; Return.ConflictingEntryPath = f.FullPath; return Return; } } foreach (File f in Files()) { if (f.Name.ToLower() == NewName.ToLower()) { Return.Entry = f; Return.CouldNotWrite = true; Return.ConflictingEntryPath = f.FullPath; return Return; } } if (new System.IO.FileInfo(Path).Length == 0) { Console.WriteLine("Creating null file"); EntryData newE = new EntryFunctions(this).GetNewEntry(this, 0, new Geometry.Flags[0], NewName); try { Console.WriteLine("Getting blocks needed"); int BlocksNeeded = 1; Console.WriteLine(sw.Elapsed.ToString()); List<uint> Blocks = new List<uint>(); Console.WriteLine("Getting new entry"); if (newE.EntryOffset >= VariousFunctions.GetBlockOffset(this.BlocksOccupied[BlocksOccupied.Length - 1], this) + this.PartitionInfo.ClusterSize) { List<uint> blocks = this.BlocksOccupied.ToList(); blocks.Add(VariousFunctions.GetBlockFromOffset(newE.EntryOffset, this.PartitionInfo)); this.BlocksOccupied = blocks.ToArray(); } Console.WriteLine(sw.Elapsed.ToString()); Blocks.Add(newE.StartingCluster); // Write the file data... // FileAction to be used fa.MaxValue = Blocks.Count; File f = new File(this.PartitionInfo, newE, this.Drive); f.Parent = this; f.FullPath = this.FullPath + "\\" + f.Name; eea.ModifiedEntry = f; Return.Entry = f; this.cachedFiles.Add(f); fa.Progress = Blocks.Count; } // This excpetion here is going to be that we're out of space... catch (Exception x) { Console.WriteLine("Exception thrown, deleting written entry"); // Delete this entry newE.NameSize = 0xE5; // Create a new entry functions class so we can get rid of this entry EntryFunctions ef = new EntryFunctions(this); // Clear the FAT chain Console.WriteLine("Clearing FAT chain"); ef.ClearFATChain(new uint[] { newE.StartingCluster }); // Mark this entry as deleted ef.CreateNewEntry(newE); throw x; } } else { Console.WriteLine(sw.Elapsed.ToString()); Console.WriteLine("Getting blocks needed"); int BlocksNeeded = (int)(VariousFunctions.UpToNearestCluster(new System.IO.FileInfo(Path).Length, PartitionInfo.ClusterSize) / PartitionInfo.ClusterSize); Console.WriteLine(sw.Elapsed.ToString()); List<uint> Blocks = new List<uint>(); Console.WriteLine("Getting new entry"); EntryData newE = new EntryFunctions(this).GetNewEntry(this, (uint)new System.IO.FileInfo(Path).Length, new Geometry.Flags[0], NewName); if (newE.EntryOffset >= VariousFunctions.GetBlockOffset(this.BlocksOccupied[BlocksOccupied.Length - 1], this) + this.PartitionInfo.ClusterSize) { List<uint> blocks = this.BlocksOccupied.ToList(); blocks.Add(VariousFunctions.GetBlockFromOffset(newE.EntryOffset, this.PartitionInfo)); this.BlocksOccupied = blocks.ToArray(); } Console.WriteLine(sw.Elapsed.ToString()); Blocks.Add(newE.StartingCluster); try { Console.WriteLine("Getting free blocks"); Blocks.AddRange(Drive.GetFreeBlocks(this, BlocksNeeded - 1, newE.StartingCluster, 0, false)); Console.WriteLine(sw.Elapsed.ToString()); } // This excpetion here is going to be that we're out of space... catch (Exception x) { Console.WriteLine("Exception thrown, deleting written entry"); // Delete this entry newE.NameSize = 0xE5; // Create a new entry functions class so we can get rid of this entry EntryFunctions ef = new EntryFunctions(this); // Clear the FAT chain Console.WriteLine("Clearing FAT chain"); ef.ClearFATChain(new uint[] { newE.StartingCluster }); // Mark this entry as deleted ef.CreateNewEntry(newE); throw x; } Console.WriteLine("Writing FAT chain"); // Write that FAT chain new EntryFunctions(this).WriteFATChain(Blocks.ToArray()); Console.WriteLine(sw.Elapsed.ToString()); // Write the file data... // FileAction to be used fa.MaxValue = Blocks.Count; // The IO to read the file Streams.Reader FileReader = null; try { FileReader = new CLKsFATXLib.Streams.Reader(new System.IO.FileStream(Path, System.IO.FileMode.Open)); } catch { System.Threading.Thread.Sleep(1000); try { FileReader = new CLKsFATXLib.Streams.Reader(new System.IO.FileStream(Path, System.IO.FileMode.Open)); } catch (Exception x) { Console.WriteLine("Exception thrown, deleting written entry"); // Delete this entry newE.NameSize = 0xE5; // Create a new entry functions class so we can get rid of this entry EntryFunctions ef = new EntryFunctions(this); // Clear the FAT chain Console.WriteLine("Clearing FAT chain"); ef.ClearFATChain(Blocks.ToArray()); // Mark this entry as deleted ef.CreateNewEntry(newE); throw x; } } // The IO to write to the destination file Streams.Writer FileWriter = Drive.Writer(); // Loop for each block... for (int i = 0; i < Blocks.Count - 1; i++) { if (fa.Cancel) { Console.WriteLine("Cancel engaged"); FileReader.Close(); File newfile = new File(this.PartitionInfo, newE, this.Drive); newfile.Parent = this; newfile.FullPath = this.FullPath + "\\" + newfile.Name; this.cachedFiles.Add(newfile); eea.FullParentPath = FullPath; eea.ModifiedEntry = newfile; eea.ParentFolder = this; OnEntryEvent(ref eea); UpdateModifiedTime(); Return.Entry = newfile; return Return; } // Set the position to the beginning of the block FileWriter.BaseStream.Position = VariousFunctions.GetBlockOffset(Blocks[i], this); for (int j = 1, k = 0; j <= 0x100; j++, k++) { if (i + k == Blocks.Count - 1) { //Console.WriteLine("Writing part of file"); FileWriter.Write(FileReader.ReadBytes((int)PartitionInfo.ClusterSize * k)); i += k; fa.Progress += k; break; } else if (Blocks[i + k] == Blocks.Count - 2 || Blocks[i + k] + 1 != Blocks[i + j] || j == 10) { //Console.WriteLine("Writing part of file"); FileWriter.Write(FileReader.ReadBytes((int)PartitionInfo.ClusterSize * j)); i += k; fa.Progress += j; break; } } OnFolderAction(ref fa); } Console.WriteLine(sw.Elapsed.ToString()); // For the last cluster, we don't know how long it is... so we use // this nifty function I made to do that for us Console.WriteLine("Seeking to final cluster"); FileWriter.BaseStream.Position = VariousFunctions.GetBlockOffset(Blocks[Blocks.Count - 1], this); // Read/write data byte[] ToWrite = new byte[(int)VariousFunctions.UpToNearest200(VariousFunctions.RemainingData(BlocksNeeded, new System.IO.FileInfo(Path).Length, this))]; if ((int)VariousFunctions.RemainingData(BlocksNeeded, new System.IO.FileInfo(Path).Length, this) < (int)VariousFunctions.UpToNearest200((int)VariousFunctions.RemainingData(BlocksNeeded, new System.IO.FileInfo(Path).Length, this))) { for (int i = (int)VariousFunctions.RemainingData(BlocksNeeded, new System.IO.FileInfo(Path).Length, this) + 1; i < ToWrite.Length; i++) { ToWrite[i] = 0xFF; } } byte[] Buffer = FileReader.ReadBytes((int)VariousFunctions.RemainingData(BlocksNeeded, new System.IO.FileInfo(Path).Length, this)); Array.Copy(Buffer, 0, ToWrite, 0, Buffer.Length); Buffer = null; Console.WriteLine("Writing final cluster"); FileWriter.Write(ToWrite); fa.Progress++; OnFolderAction(ref fa); Console.WriteLine("Closing streams"); FileReader.Close(); Console.WriteLine(sw.Elapsed.ToString()); File newF = new File(this.PartitionInfo, newE, this.Drive); newF.Parent = this; newF.FullPath = this.FullPath + "\\" + newF.Name; this.cachedFiles.Add(newF); Return.Entry = newF; eea.ModifiedEntry = newF; } eea.FullParentPath = FullPath; eea.ParentFolder = this; OnEntryEvent(ref eea); UpdateModifiedTime(); return Return; }
/// <summary> /// Creates a new, emptry file from the given path /// </summary> /// <param name="Path">Path to the file</param> /// <returns>Returns a WriteResult with a bool indicating whether or not there were problems writing the file. If true, then the Entry property will be the conflicting entry</returns> public Structs.WriteResult CreateFile(string NewName) { WriteResult Return = new WriteResult(); EntryEventArgs eea = new EntryEventArgs(); fa.CurrentFilePath = this.FullPath + "\\" + NewName; fa.CurrentFile = NewName; fa.MaxValue = 1; fa.Progress = 0; OnFolderAction(ref fa); foreach (Folder f in Folders()) { if (f.Name.ToLower() == NewName.ToLower()) { Return.Entry = f; Return.CouldNotWrite = true; Return.ConflictingEntryPath = f.FullPath; return Return; } } foreach (File f in Files()) { if (f.Name.ToLower() == NewName.ToLower()) { Return.Entry = f; Return.CouldNotWrite = true; Return.ConflictingEntryPath = f.FullPath; return Return; } } EntryData newE = new EntryFunctions(this).GetNewEntry(this, 0, new Geometry.Flags[0], NewName); int BlocksNeeded = 1; List<uint> Blocks = new List<uint>(); Console.WriteLine("Getting new entry"); if (newE.EntryOffset >= VariousFunctions.GetBlockOffset(this.BlocksOccupied[BlocksOccupied.Length - 1], this) + this.PartitionInfo.ClusterSize) { List<uint> blocks = this.BlocksOccupied.ToList(); blocks.Add(VariousFunctions.GetBlockFromOffset(newE.EntryOffset, this.PartitionInfo)); this.BlocksOccupied = blocks.ToArray(); } { Blocks.Add(newE.StartingCluster); // Write the file data... // FileAction to be used fa.MaxValue = Blocks.Count; OnFolderAction(ref fa); File f = new File(this.PartitionInfo, newE, this.Drive); f.Parent = this; f.FullPath = this.FullPath + "\\" + f.Name; eea.ModifiedEntry = f; Return.Entry = f; this.cachedFiles.Add(f); fa.Progress = Blocks.Count; OnFolderAction(ref fa); eea.FullParentPath = FullPath; eea.ParentFolder = this; OnEntryEvent(ref eea); return Return; } }