Skip to content

[Breaking change]: Updating CreationTime[Utc], LastAccessTime[Utc] and LastWriteTime[Utc] on a symbolic link no longer affects the target #31483

Closed
@jozkee

Description

@jozkee

Description

Updating those fields on a symbolic link had the effect of not change the information in the symlink itself but instead it was affecting the target.

string filename = "file";
string linkname = "link";

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));
}

Version: .NET 7 preview 1

Version

Other (please put exact version in description textbox)

Previous behavior

Updating any of the aforementioned fields on a symlink would affect the fields of the symlink's target.

Output form above program:

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

Updating any of the aforementioned fields on a symlink would affect the fields of the symlink itself.

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

Type of breaking change

  • Binary incompatible: Existing binaries may encounter a breaking change in behavior, such as failure to load/execute or different run-time behavior.
  • Source incompatible: Source code may encounter a breaking change in behavior when targeting the new runtime/component/SDK, such as compile errors or different run-time behavior.

Reason for change

Behavior was determined to be unexpected and undesirable in some cases, inconsistent with the behavior of the properties/methods that get the same fields, and it was impossible to actually update said fields in the symlink itself thorught .NET APIs, so we switched it for consistency.

Recommended action

If you were relying in this behavior, be advised that setting one of the *Time fields in a symlink won't affect the target anymore. You can use the new symbolic link APIs to obtain the target of a symlink and proceed to update that file system object instaed.

FileSystemInfo? targetInfo = linkInfo.ResolveLinkTarget(returnFinalTarget: true);
if (targetInfo  != null)
{
    // update the properties accordingly.
    targetInfo.LastWriteTime = DateTime.Now;
}

Feature area

Core .NET libraries

Affected APIs

System.IO.File.SetCreationTime(String, DateTime)
System.IO.File.SetCreationTimeUtc(String, DateTime)
System.IO.File.SetLastAccessTime(String, DateTime)
System.IO.File.SetLastAccessTimeUtc(String, DateTime)
System.IO.File.SetLastWriteTime(String, DateTime)
System.IO.File.SetLastWriteTimeUtc(String, DateTime)
System.IO.Directory.SetCreationTime(String, DateTime)
System.IO.Directory.SetCreationTimeUtc(String, DateTime)
System.IO.Directory.SetLastAccessTime(String, DateTime)
System.IO.Directory.SetLastAccessTimeUtc(String, DateTime)
System.IO.Directory.SetLastWriteTime(String, DateTime)
System.IO.Directory.SetLastWriteTimeUtc(String, DateTime)
System.IO.FileSystemInfo.CreationTime
System.IO.FileSystemInfo.CreationTimeUtc
System.IO.FileSystemInfo.LastAccessTime
System.IO.FileSystemInfo.LastAccessTimeUtc
System.IO.FileSystemInfo.LastWriteTime
System.IO.FileSystemInfo.LastWriteTimeUtc

Metadata

Metadata

Assignees

Labels

🏁 Release: .NET 7Work items for the .NET 7 releasebreaking-changeIndicates a .NET Core breaking changesource incompatibleSource code may encounter a breaking change in behavior when targeting the new version.

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions