Skip to content

Commit

Permalink
[System.IO.Compression] Fixed re-opening of disposed Zip entry streams.
Browse files Browse the repository at this point in the history
Fixes System.IO.Compression to work against Microsoft Office OpenXML SDK which depends on this behavior.

Also partial fix for https://bugzilla.xamarin.com/show_bug.cgi?id=33553.
  • Loading branch information
tritao committed Feb 19, 2016
1 parent 959f4bd commit 3745b6d
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 2 deletions.
Expand Up @@ -114,6 +114,51 @@ public void ZipGetEntryOpen()
File.Delete ("test.zip");
}

[Test]
public void ZipOpenAndReopenEntry()
{
try {
File.Copy("archive.zip", "test.zip", overwrite: true);
using (var archive = new ZipArchive(File.Open("test.zip", FileMode.Open),
ZipArchiveMode.Update))
{
var entry = archive.GetEntry("foo.txt");
Assert.IsNotNull(entry);

var stream = entry.Open();

try {
stream = entry.Open();
} catch (global::System.IO.IOException ex) {
return;
}

Assert.Fail();
}
} finally {
File.Delete ("test.zip");
}
}


[Test]
public void ZipOpenCloseAndReopenEntry()
{
File.Copy("archive.zip", "test.zip", overwrite: true);
using (var archive = new ZipArchive(File.Open("test.zip", FileMode.Open),
ZipArchiveMode.Update))
{
var entry = archive.GetEntry("foo.txt");
Assert.IsNotNull(entry);

var stream = entry.Open();
stream.Dispose();
stream = entry.Open();
}

File.Delete ("test.zip");
}

[Test]
public void ZipGetEntryDeleteReadMode()
{
Expand Down
90 changes: 88 additions & 2 deletions mcs/class/System.IO.Compression/ZipArchiveEntry.cs
Expand Up @@ -29,10 +29,96 @@

namespace System.IO.Compression
{
internal class ZipArchiveEntryStream : Stream, IDisposable
{
private readonly ZipArchiveEntry entry;
private readonly Stream stream;

public override bool CanRead {
get {
return stream.CanRead;
}
}

public override bool CanSeek {
get {
return stream.CanSeek;
}
}

public override bool CanWrite {
get {
return stream.CanWrite;
}
}

public override long Length {
get {
return stream.Length;
}
}

public override long Position {
get {
return stream.Position;
}
set {
stream.Position = value;
}
}

public ZipArchiveEntryStream(ZipArchiveEntry entry, Stream stream)
{
this.entry = entry;
this.stream = stream;
}

public override void Flush ()
{
stream.Flush();
}

public override long Seek (long offset, SeekOrigin origin)
{
return stream.Seek(offset, origin);
}

public override void SetLength (long value)
{
stream.SetLength(value);
}

public override int Read (byte[] buffer, int offset, int count)
{
return stream.Read(buffer, offset, count);
}

public override void Write (byte[] buffer, int offset, int count)
{
stream.Write(buffer, offset, count);
}

public new void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
base.Dispose();
}

protected override void Dispose(bool disposing)
{
if (disposing)
{
entry.openStream = null;
stream.Dispose();
}
}
}

public class ZipArchiveEntry
{
readonly SharpCompress.Archive.Zip.ZipArchiveEntry entry;
private Stream openStream;
internal ZipArchiveEntryStream openStream;
private bool wasDeleted;

internal ZipArchiveEntry(ZipArchive archive, SharpCompress.Archive.Zip.ZipArchiveEntry entry)
Expand Down Expand Up @@ -112,7 +198,7 @@ public Stream Open()
if (Archive.Mode == ZipArchiveMode.Create && openStream != null)
throw new IOException("The archive for this entry was opened with the Create mode, and this entry has already been written to.");

openStream = entry.OpenEntryStream();
openStream = new ZipArchiveEntryStream(this, entry.OpenEntryStream());

return openStream;
}
Expand Down

0 comments on commit 3745b6d

Please sign in to comment.