11// Licensed to the .NET Foundation under one or more agreements.
22// The .NET Foundation licenses this file to you under the MIT license.
33
4- using System . Buffers ;
54using System . Collections . Generic ;
65using System . Diagnostics ;
76using System . Diagnostics . CodeAnalysis ;
87using System . IO ;
8+ using System . IO . Enumeration ;
99using System . Runtime . InteropServices ;
1010using System . Security ;
1111using System . Text ;
@@ -271,102 +271,6 @@ private static List<string> ParseTimeZoneIds(StreamReader reader)
271271 return Path . Join ( currentPath . AsSpan ( ) , direntName ) ;
272272 }
273273
274- /// <summary>
275- /// Enumerate files
276- /// </summary>
277- private static unsafe void EnumerateFilesRecursively ( string path , Predicate < string > condition )
278- {
279- List < string > ? toExplore = null ; // List used as a stack
280-
281- int bufferSize = Interop . Sys . GetReadDirRBufferSize ( ) ;
282- byte [ ] dirBuffer = ArrayPool < byte > . Shared . Rent ( bufferSize ) ;
283- try
284- {
285- string currentPath = path ;
286-
287- fixed ( byte * dirBufferPtr = dirBuffer )
288- {
289- while ( true )
290- {
291- IntPtr dirHandle = Interop . Sys . OpenDir ( currentPath ) ;
292- if ( dirHandle == IntPtr . Zero )
293- {
294- throw Interop . GetExceptionForIoErrno ( Interop . Sys . GetLastErrorInfo ( ) , currentPath , isDirError : true ) ;
295- }
296-
297- try
298- {
299- // Read each entry from the enumerator
300- Interop . Sys . DirectoryEntry dirent ;
301- while ( Interop . Sys . ReadDirR ( dirHandle , dirBufferPtr , bufferSize , & dirent ) == 0 )
302- {
303- string ? fullPath = GetDirectoryEntryFullPath ( ref dirent , currentPath ) ;
304- if ( fullPath == null )
305- continue ;
306-
307- // Get from the dir entry whether the entry is a file or directory.
308- // We classify everything as a file unless we know it to be a directory.
309- bool isDir ;
310- if ( dirent . InodeType == Interop . Sys . NodeType . DT_DIR )
311- {
312- // We know it's a directory.
313- isDir = true ;
314- }
315- else if ( dirent . InodeType == Interop . Sys . NodeType . DT_LNK || dirent . InodeType == Interop . Sys . NodeType . DT_UNKNOWN )
316- {
317- // It's a symlink or unknown: stat to it to see if we can resolve it to a directory.
318- // If we can't (e.g. symlink to a file, broken symlink, etc.), we'll just treat it as a file.
319-
320- Interop . Sys . FileStatus fileinfo ;
321- if ( Interop . Sys . Stat ( fullPath , out fileinfo ) >= 0 )
322- {
323- isDir = ( fileinfo . Mode & Interop . Sys . FileTypes . S_IFMT ) == Interop . Sys . FileTypes . S_IFDIR ;
324- }
325- else
326- {
327- isDir = false ;
328- }
329- }
330- else
331- {
332- // Otherwise, treat it as a file. This includes regular files, FIFOs, etc.
333- isDir = false ;
334- }
335-
336- // Yield the result if the user has asked for it. In the case of directories,
337- // always explore it by pushing it onto the stack, regardless of whether
338- // we're returning directories.
339- if ( isDir )
340- {
341- toExplore ??= new List < string > ( ) ;
342- toExplore . Add ( fullPath ) ;
343- }
344- else if ( condition ( fullPath ) )
345- {
346- return ;
347- }
348- }
349- }
350- finally
351- {
352- if ( dirHandle != IntPtr . Zero )
353- Interop . Sys . CloseDir ( dirHandle ) ;
354- }
355-
356- if ( toExplore == null || toExplore . Count == 0 )
357- break ;
358-
359- currentPath = toExplore [ toExplore . Count - 1 ] ;
360- toExplore . RemoveAt ( toExplore . Count - 1 ) ;
361- }
362- }
363- }
364- finally
365- {
366- ArrayPool < byte > . Shared . Return ( dirBuffer ) ;
367- }
368- }
369-
370274 private static bool CompareTimeZoneFile ( string filePath , byte [ ] buffer , byte [ ] rawData )
371275 {
372276 try
@@ -424,7 +328,7 @@ private static string FindTimeZoneId(byte[] rawData)
424328
425329 try
426330 {
427- EnumerateFilesRecursively ( timeZoneDirectory , ( string filePath ) =>
331+ foreach ( string filePath in Directory . EnumerateFiles ( timeZoneDirectory , "*" , SearchOption . AllDirectories ) )
428332 {
429333 // skip the localtime and posixrules file, since they won't give us the correct id
430334 if ( ! string . Equals ( filePath , localtimeFilePath , StringComparison . OrdinalIgnoreCase )
@@ -440,11 +344,11 @@ private static string FindTimeZoneId(byte[] rawData)
440344 {
441345 id = id . Substring ( timeZoneDirectory . Length ) ;
442346 }
443- return true ;
347+
348+ break ;
444349 }
445350 }
446- return false ;
447- } ) ;
351+ }
448352 }
449353 catch ( IOException ) { }
450354 catch ( SecurityException ) { }
0 commit comments