@@ -1890,17 +1890,9 @@ private void Dir(
1890
1890
}
1891
1891
1892
1892
bool hidden = false ;
1893
- bool checkReparsePoint = true ;
1894
1893
if ( ! Force )
1895
1894
{
1896
1895
hidden = ( recursiveDirectory . Attributes & FileAttributes . Hidden ) != 0 ;
1897
-
1898
- // Performance optimization.
1899
- // Since we have already checked Attributes for Hidden we have already did a p/invoke
1900
- // and initialized Attributes property.
1901
- // So here we can check for ReparsePoint without new p/invoke.
1902
- // If it is not a reparse point we skip one p/invoke in IsReparsePointLikeSymlink() below.
1903
- checkReparsePoint = ( recursiveDirectory . Attributes & FileAttributes . ReparsePoint ) != 0 ;
1904
1896
}
1905
1897
1906
1898
// if "Hidden" is explicitly specified anywhere in the attribute filter, then override
@@ -1914,7 +1906,7 @@ private void Dir(
1914
1906
// c) it is not a reparse point with a target (not OneDrive or an AppX link).
1915
1907
if ( tracker == null )
1916
1908
{
1917
- if ( checkReparsePoint && InternalSymbolicLinkLinkCodeMethods . IsReparsePointLikeSymlink ( recursiveDirectory ) )
1909
+ if ( InternalSymbolicLinkLinkCodeMethods . IsReparsePointWithTarget ( recursiveDirectory ) )
1918
1910
{
1919
1911
continue ;
1920
1912
}
@@ -2066,7 +2058,7 @@ string ToModeString(FileSystemInfo fileSystemInfo)
2066
2058
public static string NameString ( PSObject instance )
2067
2059
{
2068
2060
return instance ? . BaseObject is FileSystemInfo fileInfo
2069
- ? InternalSymbolicLinkLinkCodeMethods . IsReparsePointLikeSymlink ( fileInfo )
2061
+ ? InternalSymbolicLinkLinkCodeMethods . IsReparsePointWithTarget ( fileInfo )
2070
2062
? $ "{ fileInfo . Name } -> { InternalSymbolicLinkLinkCodeMethods . GetTarget ( instance ) } "
2071
2063
: fileInfo . Name
2072
2064
: string . Empty ;
@@ -3106,31 +3098,22 @@ private void RemoveDirectoryInfoItem(DirectoryInfo directory, bool recurse, bool
3106
3098
continueRemoval = ShouldProcess ( directory . FullName , action ) ;
3107
3099
}
3108
3100
3109
- if ( InternalSymbolicLinkLinkCodeMethods . IsReparsePointLikeSymlink ( directory ) )
3101
+ if ( directory . Attributes . HasFlag ( FileAttributes . ReparsePoint ) )
3110
3102
{
3111
- void WriteErrorHelper ( Exception exception )
3112
- {
3113
- WriteError ( new ErrorRecord ( exception , errorId : "DeleteSymbolicLinkFailed" , ErrorCategory . WriteError , directory ) ) ;
3114
- }
3115
-
3116
3103
try
3117
3104
{
3118
- if ( InternalTestHooks . OneDriveTestOn )
3119
- {
3120
- WriteErrorHelper ( new IOException ( ) ) ;
3121
- return ;
3122
- }
3123
- else
3124
- {
3125
- // Name surrogates should just be detached.
3126
- directory . Delete ( ) ;
3127
- }
3105
+ // TODO:
3106
+ // Different symlinks seem to vary by behavior.
3107
+ // In particular, OneDrive symlinks won't remove without recurse,
3108
+ // but the .NET API here does not allow us to distinguish them.
3109
+ // We may need to revisit using p/Invokes here to get the right behavior
3110
+ directory . Delete ( ) ;
3128
3111
}
3129
3112
catch ( Exception e )
3130
3113
{
3131
3114
string error = StringUtil . Format ( FileSystemProviderStrings . CannotRemoveItem , directory . FullName , e . Message ) ;
3132
3115
var exception = new IOException ( error , e ) ;
3133
- WriteErrorHelper ( exception ) ;
3116
+ WriteError ( new ErrorRecord ( exception , errorId : "DeleteSymbolicLinkFailed" , ErrorCategory . WriteError , directory ) ) ;
3134
3117
}
3135
3118
3136
3119
return ;
@@ -8232,47 +8215,28 @@ internal static bool IsReparsePoint(FileSystemInfo fileInfo)
8232
8215
return fileInfo . Attributes . HasFlag ( System . IO . FileAttributes . ReparsePoint ) ;
8233
8216
}
8234
8217
8235
- internal static bool IsReparsePointLikeSymlink ( FileSystemInfo fileInfo )
8218
+ internal static bool IsReparsePointWithTarget ( FileSystemInfo fileInfo )
8236
8219
{
8237
- #if UNIX
8238
- // Reparse point on Unix is a symlink.
8239
- return IsReparsePoint ( fileInfo ) ;
8240
- #else
8241
- if ( InternalTestHooks . OneDriveTestOn && fileInfo . Name == InternalTestHooks . OneDriveTestSymlinkName )
8220
+ if ( ! IsReparsePoint ( fileInfo ) )
8242
8221
{
8243
- return ! InternalTestHooks . OneDriveTestRecurseOn ;
8222
+ return false ;
8244
8223
}
8245
-
8246
- WIN32_FIND_DATA data = default ;
8224
+ #if ! UNIX
8225
+ // It is a reparse point and we should check some reparse point tags.
8226
+ var data = new WIN32_FIND_DATA ( ) ;
8247
8227
using ( var handle = FindFirstFileEx ( fileInfo . FullName , FINDEX_INFO_LEVELS . FindExInfoBasic , ref data , FINDEX_SEARCH_OPS . FindExSearchNameMatch , IntPtr . Zero , 0 ) )
8248
8228
{
8249
- if ( handle . IsInvalid )
8250
- {
8251
- // If we can not open the file object we assume it's a symlink.
8252
- return true ;
8253
- }
8254
-
8255
- // To exclude one extra p/invoke in some scenarios
8256
- // we don't check fileInfo.FileAttributes
8257
- const int FILE_ATTRIBUTE_REPARSE_POINT = 0x0400 ;
8258
- if ( ( data . dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ) == 0 )
8259
- {
8260
- // Not a reparse point.
8261
- return false ;
8262
- }
8263
-
8264
8229
// The name surrogate bit 0x20000000 is defined in https://docs.microsoft.com/windows/win32/fileio/reparse-point-tags
8265
8230
// Name surrogates (0x20000000) are reparse points that point to other named entities local to the filesystem
8266
8231
// (like symlinks and mount points).
8267
8232
// In the case of OneDrive, they are not name surrogates and would be safe to recurse into.
8268
- if ( ( data . dwReserved0 & 0x20000000 ) == 0 && ( data . dwReserved0 != IO_REPARSE_TAG_APPEXECLINK ) )
8233
+ if ( ! handle . IsInvalid && ( data . dwReserved0 & 0x20000000 ) == 0 && ( data . dwReserved0 != IO_REPARSE_TAG_APPEXECLINK ) )
8269
8234
{
8270
8235
return false ;
8271
8236
}
8272
8237
}
8273
-
8274
- return true ;
8275
8238
#endif
8239
+ return true ;
8276
8240
}
8277
8241
8278
8242
internal static bool WinIsHardLink ( FileSystemInfo fileInfo )
0 commit comments