@@ -363,14 +363,14 @@ static void ConvertDirent(const struct dirent* entry, struct DirectoryEntry* out
363363#endif
364364}
365365
366- #if HAVE_READDIR_R
366+ #if IL2CPP_HAVE_READDIR_R_DEPRECATED_DO_NOT_USE
367367// struct dirent typically contains 64-bit numbers (e.g. d_ino), so we align it at 8-byte.
368368static const size_t dirent_alignment = 8 ;
369369#endif
370370
371371int32_t SystemNative_GetReadDirRBufferSize (void )
372372{
373- #if HAVE_READDIR_R
373+ #if IL2CPP_HAVE_READDIR_R_DEPRECATED_DO_NOT_USE
374374 // dirent should be under 2k in size
375375 assert (sizeof (struct dirent ) < 2048 );
376376 // add some extra space so we can align the buffer to dirent.
@@ -380,17 +380,25 @@ int32_t SystemNative_GetReadDirRBufferSize(void)
380380#endif
381381}
382382
383+ #if READDIR_SORT
384+ static int cmpstring (const void * p1 , const void * p2 )
385+ {
386+ return strcmp (((struct dirent * ) p1 )-> d_name , ((struct dirent * ) p2 )-> d_name );
387+ }
388+ #endif
389+
383390// To reduce the number of string copies, the caller of this function is responsible to ensure the memory
384391// referenced by outputEntry remains valid until it is read.
385392// If the platform supports readdir_r, the caller provides a buffer into which the data is read.
386393// If the platform uses readdir, the caller must ensure no calls are made to readdir/closedir since those will invalidate
387394// the current dirent. We assume the platform supports concurrent readdir calls to different DIRs.
388- int32_t SystemNative_ReadDirR (DIR * dir , uint8_t * buffer , int32_t bufferSize , struct DirectoryEntry * outputEntry )
395+ int32_t SystemNative_ReadDirR (struct DIRWrapper * dirWrapper , uint8_t * buffer , int32_t bufferSize , struct DirectoryEntry * outputEntry )
389396{
390- assert (dir != NULL );
397+ assert (dirWrapper != NULL );
398+ assert (dirWrapper -> dir != NULL );
391399 assert (outputEntry != NULL );
392400
393- #if HAVE_READDIR_R
401+ #if IL2CPP_HAVE_READDIR_R_DEPRECATED_DO_NOT_USE
394402 assert (buffer != NULL );
395403
396404 // align to dirent
@@ -445,7 +453,48 @@ int32_t SystemNative_ReadDirR(DIR* dir, uint8_t* buffer, int32_t bufferSize, str
445453 (void )buffer ; // unused
446454 (void )bufferSize ; // unused
447455 errno = 0 ;
448- struct dirent * entry = readdir (dir );
456+
457+ #if READDIR_SORT
458+ struct dirent * entry ;
459+
460+ if (!dirWrapper -> result )
461+ {
462+ size_t numEntries = 0 ;
463+ while ((entry = readdir (dirWrapper -> dir ))) numEntries ++ ;
464+ if (numEntries )
465+ {
466+ dirWrapper -> result = malloc (numEntries * sizeof (struct dirent ));
467+ dirWrapper -> curIndex = 0 ;
468+ dirWrapper -> numEntries = numEntries ;
469+ #if HAVE_REWINDDIR
470+ rewinddir (dirWrapper -> dir );
471+ #else
472+ closedir (dirWrapper -> dir );
473+ dirWrapper -> dir = opendir (dirWrapper -> dirPath );
474+ #endif
475+ size_t index = 0 ;
476+ while ((entry = readdir (dirWrapper -> dir )))
477+ {
478+ memcpy (& ((struct dirent * )dirWrapper -> result )[index ], entry , sizeof (struct dirent ));
479+ index ++ ;
480+ }
481+
482+ qsort (dirWrapper -> result , numEntries , sizeof (struct dirent ), cmpstring );
483+ }
484+ }
485+
486+ if (dirWrapper -> curIndex < dirWrapper -> numEntries )
487+ {
488+ entry = & ((struct dirent * )dirWrapper -> result )[dirWrapper -> curIndex ];
489+ dirWrapper -> curIndex ++ ;
490+ }
491+
492+ else
493+ entry = NULL ;
494+
495+ #else
496+ struct dirent * entry = readdir (dirWrapper -> dir );
497+ #endif
449498
450499 // 0 returned with null result -> end-of-stream
451500 if (entry == NULL )
@@ -465,14 +514,41 @@ int32_t SystemNative_ReadDirR(DIR* dir, uint8_t* buffer, int32_t bufferSize, str
465514 return 0 ;
466515}
467516
468- DIR * SystemNative_OpenDir (const char * path )
517+ struct DIRWrapper * SystemNative_OpenDir (const char * path )
469518{
470- return opendir (path );
519+ DIR * dir = opendir (path );
520+
521+ if (dir == NULL )
522+ return NULL ;
523+
524+ struct DIRWrapper * ret = (struct DIRWrapper * )malloc (sizeof (struct DIRWrapper ));
525+ ret -> dir = dir ;
526+ #if READDIR_SORT
527+ ret -> result = NULL ;
528+ ret -> curIndex = 0 ;
529+ ret -> numEntries = 0 ;
530+ #if !HAVE_REWINDDIR
531+ ret -> dirPath = strdup (path );
532+ #endif
533+ #endif
534+ return ret ;
471535}
472536
473- int32_t SystemNative_CloseDir (DIR * dir )
537+ int32_t SystemNative_CloseDir (struct DIRWrapper * dirWrapper )
474538{
475- return closedir (dir );
539+ assert (dirWrapper != NULL );
540+ int32_t ret = closedir (dirWrapper -> dir );
541+ #if READDIR_SORT
542+ if (dirWrapper -> result )
543+ free (dirWrapper -> result );
544+ dirWrapper -> result = NULL ;
545+ #if !HAVE_REWINDDIR
546+ if (dirWrapper -> dirPath )
547+ free (dirWrapper -> dirPath );
548+ #endif
549+ free (dirWrapper );
550+ #endif
551+ return ret ;
476552}
477553
478554int32_t SystemNative_Pipe (int32_t pipeFds [2 ], int32_t flags )
0 commit comments