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