Beispiel #1
0
            /// <summary>
            /// Creates an instance of <see cref="ICompressedArchiveAccess"/> that can be used to access a nested archive.
            /// </summary>
            /// <param name="parentArchiveAccess">The parent archive, which contains the nested archive indicated by <paramref name="entry"/>.</param>
            /// <param name="entry">The entry within <paramref name="parentArchiveAccess"/> that indicates a nested archive.</param>
            /// <returns>An instance of <see cref="NestedCompressedArchiveAccess"/>, which provides access to the nested archive.</returns>
            /// <remarks>This wrapper type takes care of cleaning up any temporary files that may be required to access the nested archive.
            /// For example, some data streams used to access an archive are not navigable from the parent stream (GZIP).</remarks>
            public static NestedCompressedArchiveAccess Create(ICompressedArchiveAccess parentArchiveAccess, ICompressedArchiveEntry entry)
            {
                NestedCompressedArchiveAccess nestedCompressedArchive = null;
                var entryName            = entry.Name;
                var nestedArchiveFormats = Path.GetExtension(entryName).GetCompressedArchiveFormatsFromFileExtension();
                var nestedArchiveFormat  = nestedArchiveFormats.FirstOrDefault();

                if (nestedArchiveFormat.IsCompressedArchiveFormatSupported())
                {
                    TemporaryDirectory temporaryLocation = null;
                    var entryData = parentArchiveAccess.OpenEntry(entry);
                    if (FormatMustBeExtracted(parentArchiveAccess.Format) || FormatMustBeExtracted(nestedArchiveFormat))
                    {
                        // We can't fully navigate the nested stream, so extract to disk, then proceed.
                        temporaryLocation = new TemporaryDirectory();
                        var temporaryEntryFilePath = Path.Combine(temporaryLocation.Path, entryName);
                        if (Directory.CreateDirectory(Path.GetDirectoryName(temporaryEntryFilePath)).Exists)
                        {
                            System.Diagnostics.Debug.WriteLine("Extracted entry " + entryName + " to " + temporaryLocation.Path);
                            var fileStream = new FileStream(temporaryEntryFilePath, FileMode.Create, FileAccess.ReadWrite);
                            entryData.CopyTo(fileStream);
                            fileStream.Seek(0, SeekOrigin.Begin);
                            entryData.Dispose();
                            entryData = fileStream;
                        }
                    }

                    var compressedArchive = CompressedArchiveAccess.Open(entryData, nestedArchiveFormat, CompressedArchiveAccessMode.Read);
                    nestedCompressedArchive = new NestedCompressedArchiveAccess(parentArchiveAccess, compressedArchive, temporaryLocation);
                    nestedCompressedArchive.NestedArchiveFormats = nestedArchiveFormats;
                }

                return(nestedCompressedArchive);
            }
Beispiel #2
0
        private static NestedCompressedArchiveAccess GetNestedCompressedArchive(ICompressedArchiveAccess compressedArchiveAccess, string locationInArchive, ref string nestedArchiveLocation)
        {
            var nestedArchiveLocations = locationInArchive.GetNestedContainerLocations();
            var entryName = nestedArchiveLocations.First();

            if (string.IsNullOrEmpty(nestedArchiveLocation))
            {
                nestedArchiveLocation = entryName + '/';
            }
            else
            {
                nestedArchiveLocation += entryName + '/';
            }
            var nestedArchiveEntry = compressedArchiveAccess.Entries.FirstOrDefault(e => e.Name.NormalizePathSeparators() == entryName);

            NestedCompressedArchiveAccess nestedCompressedArchive = null;

            if (nestedArchiveEntry != null)
            {
                nestedCompressedArchive = NestedCompressedArchiveAccess.Create(compressedArchiveAccess, nestedArchiveEntry);
                if (nestedCompressedArchive != null)
                {
                    // If there is more than one nested archive format on the location, e.g. it's a .tar.gz, or if we did not consume the entire location
                    // in the archive, then we need to recurse into this newly located archive to get to the ultimate nested archive.
                    if ((nestedCompressedArchive.NestedArchiveFormats.Count() > 1) || (nestedArchiveLocations.Length > 1))
                    {
                        locationInArchive = string.Join("/", nestedArchiveLocations, 1, nestedArchiveLocations.Length - 1) + '/';
                        if (locationInArchive.IsInNestedContainer())
                        {
                            nestedCompressedArchive = GetNestedCompressedArchive(nestedCompressedArchive, locationInArchive, ref nestedArchiveLocation);
                        }
                    }
                }
            }

            return(nestedCompressedArchive);
        }