-
Notifications
You must be signed in to change notification settings - Fork 6k
Legacy FileStream mode and symlink breaking changes #31602
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
docs/core/compatibility/core-libraries/7.0/filestream-compat-switch.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
--- | ||
title: ".NET 7 breaking change: Legacy FileStream strategy removed" | ||
description: Learn about the .NET 7 breaking change in core .NET libraries where the the ability to use the legacy `FileStream` implementation has been removed. | ||
ms.date: 10/04/2022 | ||
--- | ||
# Legacy FileStream strategy removed | ||
|
||
The `AppContext` switch `System.IO.UseNet5CompatFileStream` and the ability to use the legacy <xref:System.IO.FileStream> implementation were removed. | ||
|
||
## Previous behavior | ||
|
||
The legacy `FileStream` implementation was available and you could opt into it by using the `UseNet5CompatFileStream` switch or the `DOTNET_SYSTEM_IO_USENET5COMPATFILESTREAM` environment variable. | ||
|
||
## New behavior | ||
|
||
Starting in .NET 7, you can no longer opt in to use the legacy `FileStream` implementation. | ||
|
||
## Version introduced | ||
|
||
.NET 7 Preview 1 | ||
|
||
## Type of breaking change | ||
|
||
This change can affect [binary compatibility](../../categories.md#binary-compatibility). | ||
|
||
## Reason for change | ||
|
||
The `UseNet5CompatFileStream` switch and `DOTNET_SYSTEM_IO_USENET5COMPATFILESTREAM` environment variable were included in .NET 6 in case the new implementation caused breaking changes. Any breaking changes have now been fixed. Since there are no more bugs introduced by the `FileStream` changes, the compatibility mode was removed and with it all the legacy code, which makes the codebase easier to maintain. | ||
|
||
## Recommended action | ||
|
||
If you're currently using the switch (or the `DOTNET_SYSTEM_IO_USENET5COMPATFILESTREAM` environment variable) to opt into legacy code and are upgrading to .NET 7, the switch will no longer have any effect and you should remove it. | ||
|
||
## Affected APIs | ||
|
||
- <xref:System.IO.FileStream?displayProperty=fullName> | ||
- <xref:System.IO.File.Create(System.String)?displayProperty=fullName> | ||
- <xref:System.IO.File.Create(System.String,System.Int32)?displayProperty=fullName> | ||
- <xref:System.IO.File.Create(System.String,System.Int32,System.IO.FileOptions)?displayProperty=fullName> | ||
- <xref:System.IO.File.Create(System.String,System.Int32,System.IO.FileOptions,System.Security.AccessControl.FileSecurity)?displayProperty=fullName> | ||
- <xref:System.IO.File.Open(System.String,System.IO.FileMode)?displayProperty=fullName> | ||
- <xref:System.IO.File.Open(System.String,System.IO.FileStreamOptions)?displayProperty=fullName> | ||
- <xref:System.IO.File.Open(System.String,System.IO.FileMode,System.IO.FileAccess)?displayProperty=fullName> | ||
- <xref:System.IO.File.Open(System.String,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare)?displayProperty=fullName> | ||
- <xref:System.IO.File.OpenRead(System.String)?displayProperty=fullName> | ||
- <xref:System.IO.File.OpenWrite(System.String)?displayProperty=fullName> | ||
- <xref:System.IO.FileSystemAclExtensions.Create(System.IO.FileInfo,System.IO.FileMode,System.Security.AccessControl.FileSystemRights,System.IO.FileShare,System.Int32,System.IO.FileOptions,System.Security.AccessControl.FileSecurity)?displayProperty=fullName> | ||
- <xref:System.IO.FileInfo.Create?displayProperty=fullName> | ||
- <xref:System.IO.FileInfo.Open%2A?displayProperty=fullName> | ||
- <xref:System.IO.FileInfo.OpenRead?displayProperty=fullName> | ||
- <xref:System.IO.FileInfo.OpenWrite?displayProperty=fullName> | ||
|
||
## See also | ||
|
||
- [FileStream no longer synchronizes file offset with OS (.NET 6)](../6.0/filestream-doesnt-sync-offset-with-os.md) | ||
- [FileStream.Position updates after ReadAsync or WriteAsync completes (.NET 6)](../6.0/filestream-position-updates-after-readasync-writeasync-completion.md) |
168 changes: 168 additions & 0 deletions
168
docs/core/compatibility/core-libraries/7.0/symbolic-link-timestamps.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
--- | ||
title: ".NET 7 breaking change: Time fields on symbolic links" | ||
description: Learn about the .NET 7 breaking change in core .NET libraries where updating CreationTime[Utc], LastAccessTime[Utc], and LastWriteTime[Utc] on a symbolic link no longer affects the target . | ||
ms.date: 10/04/2022 | ||
--- | ||
# Time fields on symbolic links | ||
|
||
When changes are made to the following time-related fields on a symbolic link ("symlink"), the updates now affect the symlink itself and not the target: | ||
|
||
- <xref:System.IO.FileSystemInfo.CreationTime> | ||
- <xref:System.IO.FileSystemInfo.CreationTimeUtc> | ||
- <xref:System.IO.FileSystemInfo.LastAccessTime> | ||
- <xref:System.IO.FileSystemInfo.LastAccessTimeUtc> | ||
- <xref:System.IO.FileSystemInfo.LastWriteTime> | ||
- <xref:System.IO.FileSystemInfo.LastWriteTimeUtc> | ||
|
||
## Previous behavior | ||
|
||
Previously, updating any of the time-related fields on a symlink affected the fields of the symlink's target. | ||
|
||
Consider the following program that prints the various time field values on a file and its symbolic link, updates the symlink's time field values to 1 day later, and then reprints the time field values on both the file and symlink. | ||
|
||
```csharp | ||
string filename = "file"; | ||
string linkname = "link"; | ||
|
||
// Create a file and symlink. | ||
File.Create(filename).Dispose(); | ||
File.CreateSymbolicLink(linkname, filename); | ||
|
||
Console.WriteLine("Before update:"); | ||
PrintMetadata(filename); | ||
PrintMetadata(linkname); | ||
|
||
UpdateMetadata(linkname); | ||
|
||
Console.WriteLine("\nAfter update:"); | ||
PrintMetadata(filename); | ||
PrintMetadata(linkname); | ||
|
||
static void UpdateMetadata(string filename) | ||
{ | ||
DateTime tomorrow = DateTime.Now.AddDays(1); | ||
|
||
File.SetCreationTime(filename, tomorrow); | ||
File.SetLastAccessTime(filename, tomorrow); | ||
File.SetLastWriteTime(filename, tomorrow); | ||
File.SetAttributes(filename, File.GetAttributes(filename) | FileAttributes.Offline); | ||
} | ||
|
||
static void PrintMetadata(string filename) | ||
{ | ||
Console.WriteLine($"---{filename}---"); | ||
Console.WriteLine("Creation:\t" + File.GetCreationTime(filename)); | ||
Console.WriteLine("Last access:\t" + File.GetLastAccessTime(filename)); | ||
Console.WriteLine("Last write:\t" + File.GetLastWriteTime(filename)); | ||
Console.WriteLine("Attributes:\t" + File.GetAttributes(filename)); | ||
} | ||
``` | ||
|
||
Previously, after updating the values on the symlink, only the target file's time fields were updated. The output of the preceding program was as follows: | ||
|
||
```output | ||
Before update: | ||
---file--- | ||
Creation: 9/29/2022 10:35:40 AM | ||
Last access: 9/29/2022 10:35:40 AM | ||
Last write: 9/29/2022 10:35:40 AM | ||
Attributes: Archive | ||
---link--- | ||
Creation: 9/29/2022 10:35:40 AM | ||
Last access: 9/29/2022 10:35:40 AM | ||
Last write: 9/29/2022 10:35:40 AM | ||
Attributes: Archive, ReparsePoint | ||
|
||
After update: | ||
---file--- | ||
Creation: 9/30/2022 10:35:40 AM | ||
Last access: 9/30/2022 10:35:40 AM | ||
Last write: 9/30/2022 10:35:40 AM | ||
Attributes: Archive | ||
---link--- | ||
Creation: 9/29/2022 10:35:40 AM | ||
Last access: 9/29/2022 10:35:40 AM | ||
Last write: 9/29/2022 10:35:40 AM | ||
Attributes: Archive, ReparsePoint, Offline | ||
``` | ||
|
||
## New behavior | ||
|
||
Starting in .NET 7, updating any of the time-related fields on a symlink affects the fields of the symlink itself and not the target file. | ||
|
||
The output of the program shown in the [Previous behavior](#previous-behavior) section is as follows: | ||
|
||
```output | ||
Before update: | ||
---file--- | ||
Creation: 9/29/2022 10:33:39 AM | ||
Last access: 9/29/2022 10:33:39 AM | ||
Last write: 9/29/2022 10:33:39 AM | ||
Attributes: Archive | ||
---link--- | ||
Creation: 9/29/2022 10:33:39 AM | ||
Last access: 9/29/2022 10:33:39 AM | ||
Last write: 9/29/2022 10:33:39 AM | ||
Attributes: Archive, ReparsePoint | ||
|
||
After update: | ||
---file--- | ||
Creation: 9/29/2022 10:33:39 AM | ||
Last access: 9/29/2022 10:33:39 AM | ||
Last write: 9/29/2022 10:33:39 AM | ||
Attributes: Archive | ||
---link--- | ||
Creation: 9/30/2022 10:33:39 AM | ||
Last access: 9/30/2022 10:33:39 AM | ||
Last write: 9/30/2022 10:33:39 AM | ||
Attributes: Archive, ReparsePoint, Offline | ||
``` | ||
|
||
## Version introduced | ||
|
||
.NET 7 Preview 1 | ||
|
||
## Type of breaking change | ||
|
||
This change can affect [binary compatibility](../../categories.md#binary-compatibility). | ||
|
||
## Reason for change | ||
|
||
The previous behavior was unexpected and undesirable in some cases: | ||
|
||
- It was inconsistent with the behavior of the properties and methods that get the same fields. | ||
- It was also impossible to actually update the fields in the symlink itself using .NET APIs. | ||
|
||
## Recommended action | ||
|
||
If you were relying on this behavior to set values on the symlink's target, setting one of the `*Time` fields in a symlink will no longer affect the target. You can use the new symbolic link APIs to obtain the target of a symlink and then update that file system object instead. | ||
|
||
```csharp | ||
FileSystemInfo? targetInfo = linkInfo.ResolveLinkTarget(returnFinalTarget: true); | ||
if (targetInfo != null) | ||
{ | ||
// Update the properties accordingly. | ||
targetInfo.LastWriteTime = DateTime.Now; | ||
} | ||
``` | ||
|
||
## Affected APIs | ||
|
||
- <xref:System.IO.Directory.SetCreationTime(System.String,System.DateTime)?displayProperty=fullName> | ||
- <xref:System.IO.Directory.SetCreationTimeUtc(System.String,System.DateTime)?displayProperty=fullName> | ||
- <xref:System.IO.Directory.SetLastAccessTime(System.String,System.DateTime)?displayProperty=fullName> | ||
- <xref:System.IO.Directory.SetLastAccessTimeUtc(System.String,System.DateTime)?displayProperty=fullName> | ||
- <xref:System.IO.Directory.SetLastWriteTime(System.String,System.DateTime)?displayProperty=fullName> | ||
- <xref:System.IO.Directory.SetLastWriteTimeUtc(System.String,System.DateTime)?displayProperty=fullName> | ||
- <xref:System.IO.File.SetCreationTime(System.String,System.DateTime)?displayProperty=fullName> | ||
- <xref:System.IO.File.SetCreationTimeUtc(System.String,System.DateTime)?displayProperty=fullName> | ||
- <xref:System.IO.File.SetLastAccessTime(System.String,System.DateTime)?displayProperty=fullName> | ||
- <xref:System.IO.File.SetLastAccessTimeUtc(System.String,System.DateTime)?displayProperty=fullName> | ||
- <xref:System.IO.File.SetLastWriteTime(System.String,System.DateTime)?displayProperty=fullName> | ||
- <xref:System.IO.File.SetLastWriteTimeUtc(System.String,System.DateTime)?displayProperty=fullName> | ||
- <xref:System.IO.FileSystemInfo.CreationTime?displayProperty=fullName> | ||
- <xref:System.IO.FileSystemInfo.CreationTimeUtc?displayProperty=fullName> | ||
- <xref:System.IO.FileSystemInfo.LastAccessTime?displayProperty=fullName> | ||
- <xref:System.IO.FileSystemInfo.LastAccessTimeUtc?displayProperty=fullName> | ||
- <xref:System.IO.FileSystemInfo.LastWriteTime?displayProperty=fullName> | ||
- <xref:System.IO.FileSystemInfo.LastWriteTimeUtc?displayProperty=fullName> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.