Exemplo n.º 1
0
 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;
     }
 }
Exemplo n.º 2
0
        /// <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);
            }
        }
Exemplo n.º 3
0
        /// <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 { }
            }
        }
Exemplo n.º 4
0
        /// <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;
        }