Fix LastWriteTime and LastAccessTime of a symlink on Windows and Unix (#52639)
authorHamish Arblaster <hamarb123@gmail.com>
Mon, 15 Nov 2021 19:45:31 +0000 (06:45 +1100)
committerGitHub <noreply@github.com>
Mon, 15 Nov 2021 19:45:31 +0000 (11:45 -0800)
commitf9d05bd2f36316a0b0f2b946406fdbccad86b08f
tree06910e4c38db2ebd98e7edbdd973e1ec82343c2e
parente85de5316c9024e61547cf6c3e5b3bddf961c74a
Fix LastWriteTime and LastAccessTime of a symlink on Windows and Unix (#52639)

* Implement most of the fix for #38824

Reverts the changes in the seperate PR https://github.com/dotnet/runtime/commit/a617a01195b4dad3cb5f300962ad843b46d4f175 to fix #38824.
Does not re-enable the test because that relies on #49555, will add a seperate commit to whichever is merged last to enable the SettingUpdatesPropertiesOnSymlink test.

* Most of the code for PR #52639 to fix #38824

• Deal with merge conflicts
• Add FSOPT_NOFOLLOW for macOS and use it in setattrlist
• Use AT_SYMLINK_NOFOLLOW with utimensat (note: there doesn't seem to be an equivalent for utimes)
• Add SettingUpdatesPropertiesOnSymlink test to test if it actually sets it on the symlink itself (to the best that we can anyway ie. write + read the times)
• Specify FILE_FLAG_OPEN_REPARSE_POINT for CreateFile in FileSystem.Windows.cs (is there any other CreateFile calls that need this?)

* Remove additional FILE_FLAG_OPEN_REPARSE_POINT

I added FILE_FLAG_OPEN_REPARSE_POINT before and it was then added in another PR, this removes the duplicate entry.

* Add missing override keywords

Add missing override keywords for abstract members in the tests.

* Fix access modifiers

Fix access modifiers for tests - were meant to be protected rather than public

* Add more symlink tests, rearrange files

• Move symlink creation api to better spot in non-base files
• Add IsDirectory property for some of the new tests
• Change abstract symlink api to CreateSymlink that accepts path and target
• Create a CreateSymlinkToItem method that creates a symlink to an item that may be relative that uses the new/modified abstract CreateSymlink method
• Add SettingUpdatesPropertiesCore to avoid code duplication
• Add tests for the following variants: normal/symlink, target exists/doesn't exist, absolute/relative target
• Exclude nonexistent symlink target tests on Unix for Directories since they are counted as files

* Fix return type of CreateSymlink in File/GetSetTimes.cs

* Remove browser from new symlink tests as it doesn't support creation of symlinks

Remove browser from new symlink tests as it doesn't support creation of symlinks

* Use lutimes, improve code readability, simplify tests

• Use lutimes when it's available
• Extract dwFlagsAndAttributes to a variable
• Use same year for all tests
• Checking to delete old symlink is unnecessary, so don't
• Replace var with explicit type

* Change year in test to 2014 to reduce diff

* Rename symlink tests, use 1 core symlink times function, and check that target times don't change

Rename symlink tests, use 1 core symlink times function, and check that target times don't change

* Inline RunSymlinkTestPart 'function'

Inline RunSymlinkTestPart 'function' so that the code can be reordered so the access time test can be valid.

* Share CreateSymlinkToItem call in tests and update comment for clarity

* Update symlink time tests

• Make SettingUpdatesPropertiesOnSymlink a theory
• Remove special case for Unix due to https://github.com/dotnet/runtime/pull/52639#discussion_r739009259 (will revert if fails)
• Rename isRelative to targetIsRelative for clarity

* Remove unnecessary Assert.All

* Changes to SettingUpdatesPropertiesOnSymlink test

• Rename item field to link field
• Don't use if one-liner
• Use all time functions since only using UTC isn't necessary
• Remove the now-defunct IsDirectory property since we aren't checking it anymore

* Remove unnecessary fsi.Refresh()

• Remove unnecessary fsi.Refresh() since atime is only updated when reading a file

* Updates to test and pal_time.c

• Remove targetIsRelative cases
• Multi-line if statement
• Combine HAVE_LUTIMES and #else conditions to allow more code charing

* Remove trailing space
src/libraries/Common/src/Interop/OSX/Interop.libc.cs
src/libraries/Native/Unix/Common/pal_config.h.in
src/libraries/Native/Unix/System.Native/pal_time.c
src/libraries/Native/Unix/configure.cmake
src/libraries/System.IO.FileSystem/tests/Base/BaseGetSetTimes.cs
src/libraries/System.IO.FileSystem/tests/Directory/GetSetTimes.cs
src/libraries/System.IO.FileSystem/tests/DirectoryInfo/GetSetTimes.cs
src/libraries/System.IO.FileSystem/tests/File/GetSetTimes.cs
src/libraries/System.IO.FileSystem/tests/FileInfo/GetSetTimes.cs
src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.SetTimes.OSX.cs
src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Windows.cs