Example #1
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;
        }
Example #2
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;
        }
Example #3
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;
        }
Example #4
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;
            }
        }