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