Esempio n. 1
0
        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!");
        }
Esempio n. 2
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;
     }
 }
Esempio n. 3
0
        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);
            }
        }
Esempio n. 4
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 { }
            }
        }
Esempio n. 5
0
 public void SetFlags(byte Flags)
 {
     CLKsFATXLib.Structs.EntryData ed = EntryData;
     ed.Flags = Flags;
     EntryFunctions ef = new EntryFunctions(this);
     ef.CreateNewEntry(ed);
     this.EntryData = ed;
 }
Esempio n. 6
0
        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);
            }
        }
Esempio n. 7
0
        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;
        }
Esempio n. 8
0
        // 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;
        }
Esempio n. 9
0
 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();
 }
Esempio n. 10
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);
            }
        }
Esempio n. 11
0
        /// <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;
        }
Esempio n. 12
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;
        }
Esempio n. 13
0
        /// <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;
            }
        }