Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 6182749

Browse files
committed
Merge pull request #1911 from stephentoub/unix_zlib
Use zlib in System.IO.Compression on Unix
2 parents b90b066 + ed18842 commit 6182749

File tree

6 files changed

+124
-57
lines changed

6 files changed

+124
-57
lines changed

src/Common/src/Interop/Unix/Interop.Libraries.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ private static partial class Libraries
88
internal const string Libc = "libc"; // C library
99
internal const string LibCoreClr= "libcoreclr"; // CoreCLR runtime
1010
internal const string LibCrypto = "libcrypto"; // OpenSSL crypto library
11+
internal const string Zlib = "libz"; // zlib compression library
1112
}
1213
}

src/System.IO.Compression/src/System.IO.Compression.csproj

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,17 @@
5252
<Compile Include="System\IO\Compression\ZipVersionNeededValues.cs" />
5353
<Compile Include="System\IO\Compression\ZLibException.cs" />
5454
<Compile Include="System\IO\Compression\ZLibNative.cs" />
55-
</ItemGroup>
56-
<ItemGroup>
5755
<Compile Include="Interop\Interop.zlib.cs" />
58-
<Compile Include="$(CommonPath)\Interop\Windows\Interop.Libraries.cs" />
5956
</ItemGroup>
6057
<ItemGroup Condition=" '$(TargetsWindows)' == 'true' ">
6158
<Compile Include="System\IO\Compression\DeflateStream.Windows.cs" />
59+
<Compile Include="System\IO\Compression\ZLibNative.Windows.cs" />
60+
<Compile Include="$(CommonPath)\Interop\Windows\Interop.Libraries.cs" />
6261
</ItemGroup>
6362
<ItemGroup Condition=" '$(TargetsUnix)' == 'true' ">
6463
<Compile Include="System\IO\Compression\DeflateStream.Unix.cs" />
64+
<Compile Include="System\IO\Compression\ZLibNative.Unix.cs" />
65+
<Compile Include="$(CommonPath)\Interop\Unix\Interop.Libraries.cs" />
6566
</ItemGroup>
6667
<ItemGroup>
6768
<None Include="project.json" />
Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
11
// Copyright (c) Microsoft. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

4+
using System.Diagnostics;
5+
46
namespace System.IO.Compression
57
{
68
public partial class DeflateStream : Stream
79
{
810
private static WorkerType GetDeflaterType()
911
{
10-
return WorkerType.Managed; // TODO: Switch to ZLib once interop is worked out
12+
try
13+
{
14+
// Make any P/Invoke into zlib to ensure we're able to find and use it.
15+
// If we are, then use zlib.
16+
Interop.zlib.zlibCompileFlags();
17+
return WorkerType.ZLib;
18+
}
19+
catch
20+
{
21+
// Otherwise, fallback to managed implementation if zlib isn't available
22+
Debug.Fail("zlib unavailable");
23+
return WorkerType.Managed;
24+
}
1125
}
1226
}
1327
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System.Runtime.InteropServices;
5+
6+
namespace System.IO.Compression
7+
{
8+
internal static partial class ZLibNative
9+
{
10+
/// <summary>
11+
/// ZLib stream descriptor data structure
12+
/// Do not construct instances of <code>ZStream</code> explicitly.
13+
/// Always use <code>ZLibNative.DeflateInit2_</code> or <code>ZLibNative.InflateInit2_</code> instead.
14+
/// Those methods will wrap this structure into a <code>SafeHandle</code> and thus make sure that it is always disposed correctly.
15+
/// </summary>
16+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
17+
internal struct ZStream
18+
{
19+
internal IntPtr nextIn; //Bytef *next_in; /* next input byte */
20+
internal UIntPtr availIn; //uInt avail_in; /* number of bytes available at next_in */
21+
internal UIntPtr totalIn; //uLong total_in; /* total nb of input bytes read so far */
22+
23+
internal IntPtr nextOut; //Bytef *next_out; /* next output byte should be put there */
24+
internal UIntPtr availOut; //uInt avail_out; /* remaining free space at next_out */
25+
internal UIntPtr totalOut; //uLong total_out; /* total nb of bytes output so far */
26+
27+
internal IntPtr msg; //char *msg; /* last error message, NULL if no error */
28+
29+
internal IntPtr state; //struct internal_state FAR *state; /* not visible by applications */
30+
31+
internal IntPtr zalloc; //alloc_func zalloc; /* used to allocate the internal state */
32+
internal IntPtr zfree; //free_func zfree; /* used to free the internal state */
33+
internal IntPtr opaque; //voidpf opaque; /* private data object passed to zalloc and zfree */
34+
35+
internal int dataType; //int data_type; /* best guess about the data type: binary or text */
36+
internal UIntPtr adler; //uLong adler; /* adler32 value of the uncompressed data */
37+
internal UIntPtr reserved; //uLong reserved; /* reserved for future use */
38+
}
39+
40+
/// <summary>Casts a uint to a native zlib uLong.</summary>
41+
private static UIntPtr CastUInt32ToNativeuLong(uint value)
42+
{
43+
// Several members of ZStream are defined by zlib as uLong, which is 32-bits on
44+
// Windows, but 32-bits on 32-bit Unix and 64-bits on 64-bit Unix. The consuming code
45+
// works in terms of a 32-bit value, so we need to cast back and forth in
46+
// a platform-agnostic way, hence we have a PAL helper on Unix and one on Windows.
47+
return (UIntPtr)value;
48+
}
49+
}
50+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System.Runtime.InteropServices;
5+
6+
namespace System.IO.Compression
7+
{
8+
internal static partial class ZLibNative
9+
{
10+
/// <summary>
11+
/// ZLib stream descriptor data structure
12+
/// Do not construct instances of <code>ZStream</code> explicitly.
13+
/// Always use <code>ZLibNative.DeflateInit2_</code> or <code>ZLibNative.InflateInit2_</code> instead.
14+
/// Those methods will wrap this structure into a <code>SafeHandle</code> and thus make sure that it is always disposed correctly.
15+
/// </summary>
16+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
17+
internal struct ZStream
18+
{
19+
internal IntPtr nextIn; //Bytef *next_in; /* next input byte */
20+
internal uint availIn; //uInt avail_in; /* number of bytes available at next_in */
21+
internal uint totalIn; //uLong total_in; /* total nb of input bytes read so far */
22+
23+
internal IntPtr nextOut; //Bytef *next_out; /* next output byte should be put there */
24+
internal uint availOut; //uInt avail_out; /* remaining free space at next_out */
25+
internal uint totalOut; //uLong total_out; /* total nb of bytes output so far */
26+
27+
internal IntPtr msg; //char *msg; /* last error message, NULL if no error */
28+
29+
internal IntPtr state; //struct internal_state FAR *state; /* not visible by applications */
30+
31+
internal IntPtr zalloc; //alloc_func zalloc; /* used to allocate the internal state */
32+
internal IntPtr zfree; //free_func zfree; /* used to free the internal state */
33+
internal IntPtr opaque; //voidpf opaque; /* private data object passed to zalloc and zfree */
34+
35+
internal int dataType; //int data_type; /* best guess about the data type: binary or text */
36+
internal uint adler; //uLong adler; /* adler32 value of the uncompressed data */
37+
internal uint reserved; //uLong reserved; /* reserved for future use */
38+
}
39+
40+
/// <summary>Casts a uint to a native zlib uLong.</summary>
41+
private static uint CastUInt32ToNativeuLong(uint value)
42+
{
43+
return value;
44+
}
45+
46+
}
47+
}

src/System.IO.Compression/src/System/IO/Compression/ZLibNative.cs

Lines changed: 7 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
// Copyright (c) Microsoft. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

4-
using System.Text;
5-
using System.Runtime.InteropServices;
6-
using System.Runtime.Versioning;
7-
using System.Runtime.CompilerServices;
8-
using Microsoft.Win32.SafeHandles;
94
using System.Diagnostics.Contracts;
5+
using System.Runtime.InteropServices;
106
using System.Security;
7+
using System.Text;
118

129
namespace System.IO.Compression
1310
{
@@ -17,7 +14,7 @@ namespace System.IO.Compression
1714
///
1815
/// See also: How to choose a compression level (in comments to <code>CompressionLevel</code>.
1916
/// </summary>
20-
internal static class ZLibNative
17+
internal static partial class ZLibNative
2118
{
2219
#region Constants defined in zlib.h
2320

@@ -178,41 +175,6 @@ public enum CompressionMethod : int
178175
// More is faster and better compression with more memory usage.
179176
#endregion // Defaults for ZLib parameters
180177

181-
182-
#region ZLib stream descriptor data structure
183-
184-
/// <summary>
185-
/// Do not construct instances of <code>ZStream</code> explicitly.
186-
/// Always use <code>ZLibNative.DeflateInit2_</code> or <code>ZLibNative.InflateInit2_</code> instead.
187-
/// Those methods will wrap this structure into a <code>SafeHandle</code> and thus make sure that it is always disposed correctly.
188-
/// </summary>
189-
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
190-
internal struct ZStream
191-
{
192-
internal IntPtr nextIn; //Bytef *next_in; /* next input byte */
193-
internal UInt32 availIn; //uInt avail_in; /* number of bytes available at next_in */
194-
internal UInt32 totalIn; //uLong total_in; /* total nb of input bytes read so far */
195-
196-
internal IntPtr nextOut; //Bytef *next_out; /* next output byte should be put there */
197-
internal UInt32 availOut; //uInt avail_out; /* remaining free space at next_out */
198-
internal UInt32 totalOut; //uLong total_out; /* total nb of bytes output so far */
199-
200-
internal IntPtr msg; //char *msg; /* last error message, NULL if no error */
201-
202-
internal IntPtr state; //struct internal_state FAR *state; /* not visible by applications */
203-
204-
internal IntPtr zalloc; //alloc_func zalloc; /* used to allocate the internal state */
205-
internal IntPtr zfree; //free_func zfree; /* used to free the internal state */
206-
internal IntPtr opaque; //voidpf opaque; /* private data object passed to zalloc and zfree */
207-
208-
internal Int32 dataType; //int data_type; /* best guess about the data type: binary or text */
209-
internal UInt32 adler; //uLong adler; /* adler32 value of the uncompressed data */
210-
internal UInt32 reserved; //uLong reserved; /* reserved for future use */
211-
}
212-
213-
#endregion // ZLib stream descriptor data structure
214-
215-
216178
/**
217179
* Do not remove the nested typing of types inside of <code>System.IO.Compression.ZLibNative</code>.
218180
* This was done on purpose to:
@@ -314,12 +276,10 @@ public IntPtr NextIn
314276

315277
public UInt32 AvailIn
316278
{
317-
[SecurityCritical] get { return _zStream.availIn; }
318-
[SecurityCritical] set { _zStream.availIn = value; }
279+
[SecurityCritical] get { return (uint)_zStream.availIn; }
280+
[SecurityCritical] set { _zStream.availIn = CastUInt32ToNativeuLong(value); }
319281
}
320282

321-
public UInt32 TotalIn {[SecurityCritical] get { return _zStream.totalIn; } }
322-
323283
public IntPtr NextOut
324284
{
325285
[SecurityCritical] get { return _zStream.nextOut; }
@@ -328,16 +288,10 @@ public IntPtr NextOut
328288

329289
public UInt32 AvailOut
330290
{
331-
[SecurityCritical] get { return _zStream.availOut; }
332-
[SecurityCritical] set { _zStream.availOut = value; }
291+
[SecurityCritical] get { return (uint)_zStream.availOut; }
292+
[SecurityCritical] set { _zStream.availOut = CastUInt32ToNativeuLong(value); }
333293
}
334294

335-
public UInt32 TotalOut {[SecurityCritical] get { return _zStream.totalOut; } }
336-
337-
public Int32 DataType {[SecurityCritical] get { return _zStream.dataType; } }
338-
339-
public UInt32 Adler {[SecurityCritical] get { return _zStream.adler; } }
340-
341295
#endregion // Expose fields on ZStream for use by user / Fx code (add more as required)
342296

343297

0 commit comments

Comments
 (0)