diff --git a/docs/core/compatibility/9.0.md b/docs/core/compatibility/9.0.md index e69ec582651e5..8a000024a6371 100644 --- a/docs/core/compatibility/9.0.md +++ b/docs/core/compatibility/9.0.md @@ -25,6 +25,7 @@ If you're migrating an app to .NET 9, the breaking changes listed here might aff | Title | Type of change | Introduced version | |------------------------------------------------------------------------------------------|---------------------|--------------------| +| [Adding a ZipArchiveEntry with CompressionLevel sets ZIP central directory header general-purpose bit flags](core-libraries/9.0/compressionlevel-bits.md) | Behavioral change | Preview 5 | | [API obsoletions with custom diagnostic IDs](core-libraries/9.0/obsolete-apis-with-custom-diagnostics.md) | Source incompatible | Preview 1 | | [Creating type of array of System.Void not allowed](core-libraries/9.0/type-instance.md) | Behavioral change | Preview 1 | | [Inline array struct size limit is enforced](core-libraries/9.0/inlinearray-size.md) | Behavioral change | Preview 1 | diff --git a/docs/core/compatibility/core-libraries/9.0/compressionlevel-bits.md b/docs/core/compatibility/core-libraries/9.0/compressionlevel-bits.md new file mode 100644 index 0000000000000..dfea97854ec14 --- /dev/null +++ b/docs/core/compatibility/core-libraries/9.0/compressionlevel-bits.md @@ -0,0 +1,64 @@ +--- +title: "Breaking change: Adding a ZipArchiveEntry with CompressionLevel sets ZIP central directory header general-purpose bit flags" +description: Learn about the .NET 9 breaking change in core .NET libraries where adding a ZipArchiveEntry with a specified CompressionLevel sets the ZIP central directory header general-purpose bit flags. +ms.date: 06/03/2024 +--- +# Adding a ZipArchiveEntry with CompressionLevel sets ZIP central directory header general-purpose bit flags + +The [ZIP file specification](https://pkware.cachefly.net/webdocs/APPNOTE/APPNOTE_6.2.0.txt) defines that bits 1 & 2 of the general-purpose bit flag in a nested file record's central directory header should be used to indicate the compression level of the nested file. + +.NET Framework sets these bits when generating the ZIP files underpinning the API. During the migration of .NET Framework code to .NET, this functionality was lost and in .NET, bits 1 & 2 were always set to `0` when new file records were created within the ZIP file. This breaking change restores that capability. However, existing .NET clients that specify a when calling will see the general-purpose bit flag values change. + +## Previous behavior + +Previously, .NET preserved the general-purpose bits for every already in a when it was loaded and new entries were added. However, calling always resulted in bits 1 & 2 being left at a default value of `0`, even if a other than was used. + +This behavior had a downstream effect: calling with any resulted in bits 1 & 2 being left unset (and thus the was always persisted to the ZIP file as ). + +## New behavior + +Starting in .NET 9, the parameter is mapped to the general-purpose bit flags as indicated in the following table. + +| `CompressionLevel` | Bit 1 | Bit 2 | +|--------------------|-------|-------| +| `NoCompression` | 0 | 0 | +| `Optimal` | 0 | 0 | +| `SmallestSize` | 1 | 0 | +| `Fastest` | 1 | 1 | + +If you call and specify , the nested file record's compression method is set to `Stored` (rather than the default value of `Deflate`.) + +The general-purpose bits for `ZipArchiveEntry` records that already exist in a `ZipArchive` are still preserved if a new `ZipArchiveEntry` is added. + +The `CompressionOption` enumeration values in are mapped to `CompressionLevel` (and result in the corresponding bits being set) as shown in the following table. + +| `CompressionOption` | `CompressionLevel` | +|---------------------|------------------------------------------------------| +| `NotCompressed` | `NoCompression` | +| `Normal` | `Optimal` | +| `Maximum` | `SmallestSize` (.NET Framework)
`Optimal` (.NET) | +| `Fast` | `Fastest` | +| `SuperFast` | `Fastest` | + +## Version introduced + +.NET 9 Preview 5 + +## Type of breaking change + +This change is a [behavioral change](../../categories.md#behavioral-change). + +## Reason for change + +This breaking change was introduced to restore the existing .NET Framework behavior, which was omitted from .NET at the point of porting. This change also gives downstream clients (such as ) control over the value of these bits. + +## Recommended action + +If you want to ensure that new `ZipArchiveEntry` records added to the `ZipArchive` have general-purpose bit flags of `0`, specify a `CompressionLevel` of `CompressionLevel.Optimal` or `CompressionLevel.NoCompression` when you call . + +If you use to add parts to an OPC package, specify a `CompressionOption` of `CompressionOption.NotCompressed` or `CompressionOption.Normal`. + +## Affected APIs + +- +- diff --git a/docs/core/compatibility/toc.yml b/docs/core/compatibility/toc.yml index 3c9a1cce57251..ca0c69223c051 100644 --- a/docs/core/compatibility/toc.yml +++ b/docs/core/compatibility/toc.yml @@ -16,6 +16,8 @@ items: items: - name: API obsoletions with custom diagnostic IDs href: core-libraries/9.0/obsolete-apis-with-custom-diagnostics.md + - name: Adding a ZipArchiveEntry sets header general-purpose bit flags + href: core-libraries/9.0/compressionlevel-bits.md - name: Creating type of array of System.Void not allowed href: core-libraries/9.0/type-instance.md - name: Inline array struct size limit is enforced @@ -1159,7 +1161,7 @@ items: - name: Default ASP.NET Core port changed to 8080 href: containers/8.0/aspnet-port.md - name: Kerberos package removed from Alpine and Debian images - href: containers/8.0/krb5-libs-package.md + href: containers/8.0/krb5-libs-package.md - name: libintl package removed from Alpine images href: containers/8.0/libintl-package.md - name: Multi-platform container tags are Linux-only @@ -1170,6 +1172,10 @@ items: items: - name: .NET 9 items: + - name: API obsoletions with custom diagnostic IDs + href: core-libraries/9.0/obsolete-apis-with-custom-diagnostics.md + - name: Adding a ZipArchiveEntry sets header general-purpose bit flags + href: core-libraries/9.0/compressionlevel-bits.md - name: Creating type of array of System.Void not allowed href: core-libraries/9.0/type-instance.md - name: Inline array struct size limit is enforced diff --git a/docs/fundamentals/code-analysis/code-quality-rule-options.md b/docs/fundamentals/code-analysis/code-quality-rule-options.md index 2bd7b66d85cfb..a3625dd1be658 100644 --- a/docs/fundamentals/code-analysis/code-quality-rule-options.md +++ b/docs/fundamentals/code-analysis/code-quality-rule-options.md @@ -25,8 +25,8 @@ Each refining option can be configured for all rules, for a category of rules (f The syntax for configuring an option for *all* rules is as follows: -|Syntax|Example| -|-|-| +| Syntax | Example | +|----------------------------------------------------|--------------------------------------------| | dotnet_code_quality.\ = \ | `dotnet_code_quality.api_surface = public` | The values for `` are listed under [Options](#options). @@ -35,8 +35,8 @@ The values for `` are listed under [Options](#options). The syntax for configuring an option for a [*category* of rules](categories.md) is as follows: -|Syntax|Example| -|-|-| +| Syntax | Example | +|-----------------------------------------------------------------|---------------------------------------------------| | dotnet_code_quality.\.\ = OptionValue | `dotnet_code_quality.Naming.api_surface = public` | The following table lists the available values for ``. @@ -65,8 +65,8 @@ The following table lists the available values for ``. The syntax for configuring an option for a *specific* rule is as follows: -|Syntax|Example| -|-|-| +| Syntax | Example | +|--------------------------------------------------------------|---------------------------------------------------| | dotnet_code_quality.\.\ = \ | `dotnet_code_quality.CA1040.api_surface = public` | ## Options