mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-07-08 18:16:30 +00:00
intermediate commit
This commit is contained in:
@@ -280,7 +280,7 @@ Archive API:
|
||||
|
||||
- `TarArchive.OpenArchive(Stream)` and `TarArchive.OpenAsyncArchive(Stream)` require seekable raw tar streams.
|
||||
- File/path overloads own the opened file stream.
|
||||
- Compressed tar wrappers are supported through `TarReader`, not `TarArchive`.
|
||||
- Compressed tar wrappers are supported through `TarReader`, not `TarArchive` or `ArchiveFactory`; archive detection blocks them instead of opening the outer compression wrapper as a standalone archive.
|
||||
|
||||
Parsed metadata surfaced through entries includes:
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ using (var archive = ArchiveFactory.OpenArchive(parts))
|
||||
}
|
||||
```
|
||||
|
||||
`ArchiveInformation.SupportsRandomAccess` is `true` when the detected format supports `IArchive` random access. It is `false` for reader-only formats such as Ace, Arc, Arj, and standalone LZW, where `ReaderFactory.OpenReader` should be used instead. Compressed tar wrappers such as `.tar.gz` and `.tar.xz` are also reader-only; use `ReaderFactory.OpenReader` or `TarReader.OpenReader` for those files.
|
||||
`ArchiveInformation.SupportsRandomAccess` is `true` when the detected format supports `IArchive` random access. It is `false` for reader-only formats such as Ace, Arc, Arj, and standalone LZW, where `ReaderFactory.OpenReader` should be used instead. Compressed tar wrappers such as `.tar.gz` and `.tar.xz` are also reader-only; `ArchiveFactory.GetArchiveInformation` returns `null` for them and `ArchiveFactory.OpenArchive` does not open them as the outer compression wrapper. Use `ReaderFactory.OpenReader` or `TarReader.OpenReader` for those files.
|
||||
|
||||
### Creating Archives
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
4. The 7Zip format doesn't allow for reading as a forward-only stream, so 7Zip read support is only through the Archive API. Writing is supported through SevenZipWriter for non-solid archives with LZMA/LZMA2 and requires a seekable output stream. See [7Zip Format Notes](#7zip-format-notes) for details on async extraction behavior.
|
||||
5. LZip has no support for extra data like the file name or timestamp. There is a default filename used when looking at the entry Key on the archive.
|
||||
|
||||
`ArchiveFactory.GetArchiveInformation(...).SupportsRandomAccess` is `true` when the detected format has an Archive API in this table. It is `false` for reader-only formats such as Ace, Arc, Arj, and standalone LZW. Compressed tar wrappers are supported by `ReaderFactory`/`TarReader`, not by `ArchiveFactory`/`TarArchive`.
|
||||
`ArchiveFactory.GetArchiveInformation(...).SupportsRandomAccess` is `true` when the detected format has an Archive API in this table. It is `false` for reader-only formats such as Ace, Arc, Arj, and standalone LZW. Compressed tar wrappers are supported by `ReaderFactory`/`TarReader`, not by `ArchiveFactory`/`TarArchive`; ArchiveFactory detection blocks them instead of opening the outer compression wrapper as a standalone archive.
|
||||
|
||||
### Zip Format Notes
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ Implications:
|
||||
- Tar detection is content-based, not extension-based.
|
||||
- Wrapper detection is not sufficient by itself. The decompressed payload must also parse as tar.
|
||||
- Non-seekable wrapper detection is supported through the recording and rewind mechanism on the reader path.
|
||||
- `ArchiveFactory`/`TarArchive` do not open compressed tar wrappers; use `ReaderFactory`/`TarReader` for `.tar.gz`, `.tar.bz2`, `.tar.xz`, `.tar.zst`, `.tar.lz`, and `.tar.Z`.
|
||||
- `ArchiveFactory`/`TarArchive` do not open compressed tar wrappers and do not fall through to the outer compression wrapper archive; use `ReaderFactory`/`TarReader` for `.tar.gz`, `.tar.bz2`, `.tar.xz`, `.tar.zst`, `.tar.lz`, and `.tar.Z`.
|
||||
- The largest rewind requirement currently comes from BZip2, which declares a larger minimum probe buffer in `TarWrapper`.
|
||||
|
||||
`TarArchive.IsTarFile` and `TarArchive.IsTarFileAsync` attempt to read a single tar header and return `false` on any exception. They also treat an all-zero empty archive block as a valid empty tar archive when the entry type is defined.
|
||||
|
||||
@@ -409,7 +409,6 @@ public class ArchiveFactoryTests : TestBase
|
||||
[InlineData("Tar.noEmptyDirs.tar", ArchiveType.Tar, true)]
|
||||
[InlineData("Tar.tar", ArchiveType.Tar, true)]
|
||||
[InlineData("TarCorrupted.tar", ArchiveType.Tar, true)]
|
||||
[InlineData("TarWithSymlink.tar.gz", ArchiveType.GZip, true)]
|
||||
[InlineData("WinZip26.zip", ArchiveType.Zip, true)]
|
||||
[InlineData("WinZip26_BZip2.zipx", ArchiveType.Zip, true)]
|
||||
[InlineData("WinZip26_LZMA.zipx", ArchiveType.Zip, true)]
|
||||
@@ -567,7 +566,6 @@ public class ArchiveFactoryTests : TestBase
|
||||
[InlineData("Tar.noEmptyDirs.tar", ArchiveType.Tar, true)]
|
||||
[InlineData("Tar.tar", ArchiveType.Tar, true)]
|
||||
[InlineData("TarCorrupted.tar", ArchiveType.Tar, true)]
|
||||
[InlineData("TarWithSymlink.tar.gz", ArchiveType.GZip, true)]
|
||||
[InlineData("WinZip26.zip", ArchiveType.Zip, true)]
|
||||
[InlineData("WinZip26_BZip2.zipx", ArchiveType.Zip, true)]
|
||||
[InlineData("WinZip26_LZMA.zipx", ArchiveType.Zip, true)]
|
||||
@@ -658,6 +656,58 @@ public class ArchiveFactoryTests : TestBase
|
||||
Assert.Null(info);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Tar.tar.gz")]
|
||||
[InlineData("Tar.tar.Z")]
|
||||
public void IsArchive_ReturnsFalse_ForCompressedTar(string archiveName)
|
||||
{
|
||||
using var stream = File.OpenRead(GetTestArchivePath(archiveName));
|
||||
|
||||
var isArchive = ArchiveFactory.IsArchive(stream, out var archiveType);
|
||||
|
||||
Assert.False(isArchive);
|
||||
Assert.Null(archiveType);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Tar.tar.gz")]
|
||||
[InlineData("Tar.tar.Z")]
|
||||
public async ValueTask IsArchiveAsync_ReturnsFalse_ForCompressedTar(string archiveName)
|
||||
{
|
||||
using var stream = File.OpenRead(GetTestArchivePath(archiveName));
|
||||
|
||||
var (isArchive, archiveType) = await ArchiveFactory.IsArchiveAsync(stream);
|
||||
|
||||
Assert.False(isArchive);
|
||||
Assert.Null(archiveType);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Tar.tar.gz")]
|
||||
[InlineData("Tar.tar.Z")]
|
||||
public void GetArchiveInformation_ReturnsNull_ForCompressedTar(string archiveName)
|
||||
{
|
||||
using var stream = File.OpenRead(GetTestArchivePath(archiveName));
|
||||
|
||||
var info = ArchiveFactory.GetArchiveInformation(stream);
|
||||
|
||||
Assert.Null(info);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Tar.tar.gz")]
|
||||
[InlineData("Tar.tar.Z")]
|
||||
public async ValueTask GetArchiveInformationAsync_ReturnsNull_ForCompressedTar(
|
||||
string archiveName
|
||||
)
|
||||
{
|
||||
using var stream = File.OpenRead(GetTestArchivePath(archiveName));
|
||||
|
||||
var info = await ArchiveFactory.GetArchiveInformationAsync(stream);
|
||||
|
||||
Assert.Null(info);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Zip.deflate.zip", ArchiveType.Zip)]
|
||||
[InlineData("Tar.noEmptyDirs.tar", ArchiveType.Tar)]
|
||||
|
||||
@@ -35,16 +35,30 @@ public class TarArchiveAsyncTests : ArchiveTests
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async ValueTask TarArchiveOpenAsyncArchive_RejectsCompressedTar()
|
||||
[Theory]
|
||||
[InlineData("Tar.tar.gz")]
|
||||
[InlineData("Tar.tar.Z")]
|
||||
public async ValueTask TarArchiveOpenAsyncArchive_RejectsCompressedTar(string archiveName)
|
||||
{
|
||||
using Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"));
|
||||
using Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, archiveName));
|
||||
|
||||
await Assert.ThrowsAsync<InvalidFormatException>(async () =>
|
||||
await TarArchive.OpenAsyncArchive(stream)
|
||||
);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Tar.tar.gz")]
|
||||
[InlineData("Tar.tar.Z")]
|
||||
public async ValueTask ArchiveFactoryOpenAsyncArchive_RejectsCompressedTar(string archiveName)
|
||||
{
|
||||
using Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, archiveName));
|
||||
|
||||
await Assert.ThrowsAsync<ArchiveOperationException>(async () =>
|
||||
await ArchiveFactory.OpenAsyncArchive(stream)
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async ValueTask TarArchiveOpenAsyncStream_Throws_On_Unreadable_Stream()
|
||||
{
|
||||
|
||||
@@ -486,19 +486,22 @@ public class TarArchiveTests : ArchiveTests
|
||||
Assert.False(isTar);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ArchiveFactoryStreamRead_Autodetect_CompressedTar_AsGZip()
|
||||
[Theory]
|
||||
[InlineData("Tar.tar.gz")]
|
||||
[InlineData("Tar.tar.Z")]
|
||||
public void ArchiveFactoryStreamRead_Autodetect_RejectsCompressedTar(string archiveName)
|
||||
{
|
||||
using Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"));
|
||||
using var archive = ArchiveFactory.OpenArchive(stream);
|
||||
using Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, archiveName));
|
||||
|
||||
Assert.Equal(ArchiveType.GZip, archive.Type);
|
||||
Assert.Throws<ArchiveOperationException>(() => ArchiveFactory.OpenArchive(stream));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TarArchiveOpenArchive_RejectsCompressedTar()
|
||||
[Theory]
|
||||
[InlineData("Tar.tar.gz")]
|
||||
[InlineData("Tar.tar.Z")]
|
||||
public void TarArchiveOpenArchive_RejectsCompressedTar(string archiveName)
|
||||
{
|
||||
using Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"));
|
||||
using Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, archiveName));
|
||||
|
||||
Assert.Throws<InvalidFormatException>(() => TarArchive.OpenArchive(stream));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user