Iterating TarArchive.Entries fails if EntryStream.CopyToAsync called #77

Open
opened 2026-01-29 22:06:15 +00:00 by claunia · 4 comments
Owner

Originally created by @matthewDDennis on GitHub (Jan 18, 2016).

The following code fails if the archive.Entries.ToList() is changed to archive.Entries. I suspect that there is interaction with the streams. So calling ToList() prevents this as the Enumeration of the Entries will complete its use of the stream.

using (var fileStream = fileinfo.OpenRead())
{
    using (var gzipStream = new GZipStream(fileStream, CompressionMode.Decompress))
    {
        using (var memStream = new MemoryStream())
        {
            await gzipStream.CopyToAsync(memStream);
            memStream.Position = 0;
            using (var archive = SharpCompress.Archive.Tar.TarArchive.Open(memStream))
            {
                foreach (var entry in archive.Entries.ToList())
                {
                    if (!entry.IsDirectory && entry.Key.EndsWith(".json"))
                    {
                        var outputFileName = $"{dataDir.FullName}\\{entry.Key.Substring(2)}";
                        Console.WriteLine($"Extracting {outputFileName}");

                        var outputFile = new FileInfo(outputFileName);
                        using (var outputStream = outputFile.OpenWrite())
                        {
                            using (var entryStream = entry.OpenEntryStream())
                            {
                                await entryStream.CopyToAsync(outputStream);
                            }
                        }
                    }
                }
            }
            Console.WriteLine($"Opened file {fileinfo.FullName}");
        }
    }
Originally created by @matthewDDennis on GitHub (Jan 18, 2016). The following code fails if the `archive.Entries.ToList()` is changed to `archive.Entries`. I suspect that there is interaction with the streams. So calling `ToList()` prevents this as the Enumeration of the Entries will complete its use of the stream. ``` c# using (var fileStream = fileinfo.OpenRead()) { using (var gzipStream = new GZipStream(fileStream, CompressionMode.Decompress)) { using (var memStream = new MemoryStream()) { await gzipStream.CopyToAsync(memStream); memStream.Position = 0; using (var archive = SharpCompress.Archive.Tar.TarArchive.Open(memStream)) { foreach (var entry in archive.Entries.ToList()) { if (!entry.IsDirectory && entry.Key.EndsWith(".json")) { var outputFileName = $"{dataDir.FullName}\\{entry.Key.Substring(2)}"; Console.WriteLine($"Extracting {outputFileName}"); var outputFile = new FileInfo(outputFileName); using (var outputStream = outputFile.OpenWrite()) { using (var entryStream = entry.OpenEntryStream()) { await entryStream.CopyToAsync(outputStream); } } } } } Console.WriteLine($"Opened file {fileinfo.FullName}"); } } ```
Author
Owner

@matthewDDennis commented on GitHub (Jan 18, 2016):

A quick look at the code shows that TarArchive.Entries is using yield. Thus, it will allow the Stream to be repositioned between each Entry causing the reading of the headers to fail due to the position change.

@matthewDDennis commented on GitHub (Jan 18, 2016): A quick look at the code shows that `TarArchive.Entries` is using `yield`. Thus, it will allow the `Stream` to be repositioned between each `Entry` causing the reading of the headers to fail due to the position change.
Author
Owner

@adamhathcock commented on GitHub (Jan 19, 2016):

Is this only an issue if you use CopyToAsync? I haven't looked at the code just yet but your statement seems to imply that.

I hope not. Otherwise, the bug might be more serious :)

@adamhathcock commented on GitHub (Jan 19, 2016): Is this only an issue if you use CopyToAsync? I haven't looked at the code just yet but your statement seems to imply that. I hope not. Otherwise, the bug might be more serious :)
Author
Owner

@iamcarbon commented on GitHub (Jun 22, 2017):

Ran into this as well. Creating an array form the entries before enumerating solved the problem.

@iamcarbon commented on GitHub (Jun 22, 2017): Ran into this as well. Creating an array form the entries before enumerating solved the problem.
Author
Owner

@Eli-Black-Work commented on GitHub (Sep 6, 2019):

I'm seeing this as well, but after calling OpenEntryStream().ReadAsync() on an entry while iterating through TarArchive.Entries

iamcarbon's fix worked; thanks :)

@Eli-Black-Work commented on GitHub (Sep 6, 2019): I'm seeing this as well, but after calling OpenEntryStream().ReadAsync() on an entry while iterating through TarArchive.Entries iamcarbon's fix worked; thanks :)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/sharpcompress#77