Exemple #1
0
        /// <summary>
        /// Modifies a current key as a new entry.
        /// </summary>
        /// <param name="infoKey">Entry to modify.</param>
        /// <param name="newEntryPath">Path for the entry.</param>
        /// <returns></returns>
        private FileInfoKey ModifyExistingEntryAsNew(FileInfoKey infoKey, string newEntryPath)
        {
            // Check paths
            string[]       pathParts      = newEntryPath.Split(Path.AltDirectorySeparatorChar);
            FileEntryBTree currentSubTree = Files[0];

            uint newKeyIndex = NextEntryIndex();

            // Find the entry key and update it
            for (int i = 0; i < pathParts.Length; i++)
            {
                if (i != pathParts.Length - 1)
                {
                    // Check actual folders
                    int keyIndex = FileNames.GetIndexOfString(pathParts[i]);
                    if (keyIndex == -1)
                    {
                        throw new ArgumentNullException($"Entry Key for file info key ({infoKey}) has missing file name key: {pathParts[i]}");
                    }

                    FileEntryKey subTreeKey = currentSubTree.GetFolderEntryByNameIndex((uint)keyIndex);

                    if (subTreeKey is null)
                    {
                        throw new InvalidOperationException($"Tried to modify existing key {newEntryPath} (str index: {keyIndex}), but missing in entries");
                    }
                    else if (!subTreeKey.Flags.HasFlag(EntryKeyFlags.Directory))
                    {
                        throw new InvalidOperationException($"Tried to modify existing key {newEntryPath} but entry key ({subTreeKey}) is not marked as directory. Is the volume corrupted?");
                    }

                    currentSubTree = Files[(int)subTreeKey.EntryIndex];
                }
                else
                {
                    // Got the location for the subtree

                    // Get our actual file entry key
                    FileEntryKey entryKey = currentSubTree.Entries.FirstOrDefault(e => e.EntryIndex == infoKey.FileIndex);
                    if (entryKey is null)
                    {
                        throw new ArgumentNullException($"Entry Key for file info key ({infoKey}) is missing while modifying.");
                    }

                    // Update it actually
                    entryKey.EntryIndex = newKeyIndex;
                }
            }

            // Find the original entry key, copy from it, add to the tree
            foreach (FileEntryBTree tree in Files)
            {
                foreach (FileEntryKey child in tree.Entries)
                {
                    if (child.EntryIndex == infoKey.FileIndex) // If the entry key exists, add it
                    {
                        var fileInfo = new FileInfoKey(newKeyIndex);
                        fileInfo.CompressedSize   = infoKey.CompressedSize;
                        fileInfo.UncompressedSize = infoKey.UncompressedSize;
                        fileInfo.SegmentIndex     = NextSegmentIndex(); // Pushed to the end, so technically the segment is new, will be readjusted at the end anyway
                        fileInfo.Flags            = infoKey.Flags;
                        FileInfos.Entries.Add(fileInfo);
                        return(fileInfo);
                    }
                }
            }

            // If it wasn't found, then we already have it
            infoKey.FileIndex = newKeyIndex;

            // Move it to the last
            FileInfos.Entries.Remove(infoKey);
            FileInfos.Entries.Add(infoKey);
            return(infoKey);
        }