@@ -506,16 +506,16 @@ fnmatch(
506506VALUE rb_cDir ;
507507static VALUE sym_directory , sym_link , sym_file , sym_unknown ;
508508
509- #ifdef DT_BLK
509+ #if defined( DT_BLK ) || defined( S_IFBLK )
510510static VALUE sym_block_device ;
511511#endif
512- #ifdef DT_CHR
512+ #if defined( DT_CHR ) || defined( S_IFCHR )
513513static VALUE sym_character_device ;
514514#endif
515- #ifdef DT_FIFO
515+ #if defined( DT_FIFO ) || defined( S_IFIFO )
516516static VALUE sym_fifo ;
517517#endif
518- #ifdef DT_SOCK
518+ #if defined( DT_SOCK ) || defined( S_IFSOCK )
519519static VALUE sym_socket ;
520520#endif
521521
@@ -919,19 +919,26 @@ dir_read(VALUE dir)
919919 }
920920}
921921
922- static VALUE dir_each_entry (VALUE , VALUE (* )(VALUE , VALUE , unsigned char ), VALUE , int );
922+ struct dir_entry_args {
923+ struct dir_data * dirp ;
924+ struct dirent * dp ;
925+ };
926+
927+ static VALUE dir_each_entry (VALUE , VALUE (* )(VALUE , VALUE , struct dir_entry_args * ), VALUE , int );
923928
924929static VALUE
925- dir_yield (VALUE arg , VALUE path , unsigned char dtype )
930+ dir_yield (VALUE arg , VALUE path , struct dir_entry_args * _unused )
926931{
927932 return rb_yield (path );
928933}
929934
935+ static int do_lstat (int fd , const char * path , struct stat * pst , int flags , rb_encoding * enc );
936+
930937static VALUE
931- dir_yield_with_type (VALUE arg , VALUE path , unsigned char dtype )
938+ dir_yield_with_type (VALUE arg , VALUE path , struct dir_entry_args * dir_entry )
932939{
933940 VALUE type ;
934- switch (dtype ) {
941+ switch (dir_entry -> dp -> d_type ) {
935942#ifdef DT_BLK
936943 case DT_BLK :
937944 type = sym_block_device ;
@@ -966,6 +973,47 @@ dir_yield_with_type(VALUE arg, VALUE path, unsigned char dtype)
966973 break ;
967974 }
968975
976+ #ifdef HAVE_DIRFD
977+ if (RUBY_DEBUG || RB_UNLIKELY (type == sym_unknown )) {
978+ struct stat st ;
979+ if (do_lstat (dirfd (dir_entry -> dirp -> dir ), dir_entry -> dp -> d_name , & st , 0 , rb_filesystem_encoding ()) == 0 ) {
980+ switch (st .st_mode & S_IFMT ) {
981+ case S_IFDIR :
982+ type = sym_directory ;
983+ break ;
984+ case S_IFLNK :
985+ type = sym_link ;
986+ break ;
987+ case S_IFREG :
988+ type = sym_file ;
989+ break ;
990+ #ifdef S_IFSOCK
991+ case S_IFSOCK :
992+ type = sym_socket ;
993+ break ;
994+ #endif
995+ #ifdef S_IFIFO
996+ case S_IFIFO :
997+ type = sym_fifo ;
998+ break ;
999+ #endif
1000+ #ifdef S_IFBLK
1001+ case S_IFBLK :
1002+ type = sym_block_device ;
1003+ break ;
1004+ #endif
1005+ #ifdef S_IFCHR
1006+ case S_IFCHR :
1007+ type = sym_character_device ;
1008+ break ;
1009+ #endif
1010+ default :
1011+ break ;
1012+ }
1013+ }
1014+ }
1015+ #endif // HAVE_DIRFD
1016+
9691017 if (NIL_P (arg )) {
9701018 return rb_yield_values (2 , path , type );
9711019 }
@@ -1001,7 +1049,7 @@ dir_each(VALUE dir)
10011049}
10021050
10031051static VALUE
1004- dir_each_entry (VALUE dir , VALUE (* each )(VALUE , VALUE , unsigned char ), VALUE arg , int children_only )
1052+ dir_each_entry (VALUE dir , VALUE (* each )(VALUE , VALUE , struct dir_entry_args * ), VALUE arg , int children_only )
10051053{
10061054 struct dir_data * dirp ;
10071055 struct dirent * dp ;
@@ -1027,7 +1075,11 @@ dir_each_entry(VALUE dir, VALUE (*each)(VALUE, VALUE, unsigned char), VALUE arg,
10271075 else
10281076#endif
10291077 path = rb_external_str_new_with_enc (name , namlen , dirp -> enc );
1030- (* each )(arg , path , dp -> d_type );
1078+ struct dir_entry_args each_args = {
1079+ .dirp = dirp ,
1080+ .dp = dp ,
1081+ };
1082+ (* each )(arg , path , & each_args );
10311083 }
10321084 return dir ;
10331085}
@@ -1865,7 +1917,7 @@ nogvl_stat(void *args)
18651917
18661918/* System call with warning */
18671919static int
1868- do_stat (int fd , size_t baselen , const char * path , struct stat * pst , int flags , rb_encoding * enc )
1920+ do_stat (int fd , const char * path , struct stat * pst , int flags , rb_encoding * enc )
18691921{
18701922#if USE_OPENDIR_AT
18711923 struct fstatat_args args ;
@@ -1897,7 +1949,7 @@ nogvl_lstat(void *args)
18971949#endif
18981950
18991951static int
1900- do_lstat (int fd , size_t baselen , const char * path , struct stat * pst , int flags , rb_encoding * enc )
1952+ do_lstat (int fd , const char * path , struct stat * pst , int flags , rb_encoding * enc )
19011953{
19021954#if USE_OPENDIR_AT
19031955 struct fstatat_args args ;
@@ -2840,15 +2892,15 @@ glob_helper(
28402892
28412893 if (* path ) {
28422894 if (match_all && pathtype == path_unknown ) {
2843- if (do_lstat (fd , baselen , path , & st , flags , enc ) == 0 ) {
2895+ if (do_lstat (fd , path , & st , flags , enc ) == 0 ) {
28442896 pathtype = IFTODT (st .st_mode );
28452897 }
28462898 else {
28472899 pathtype = path_noent ;
28482900 }
28492901 }
28502902 if (match_dir && (pathtype == path_unknown || pathtype == path_symlink )) {
2851- if (do_stat (fd , baselen , path , & st , flags , enc ) == 0 ) {
2903+ if (do_stat (fd , path , & st , flags , enc ) == 0 ) {
28522904 pathtype = IFTODT (st .st_mode );
28532905 }
28542906 else {
@@ -2976,7 +3028,7 @@ glob_helper(
29763028 if (recursive && dotfile < ((flags & FNM_DOTMATCH ) ? 2 : 1 ) &&
29773029 new_pathtype == path_unknown ) {
29783030 /* RECURSIVE never match dot files unless FNM_DOTMATCH is set */
2979- if (do_lstat (fd , baselen , buf , & st , flags , enc ) == 0 )
3031+ if (do_lstat (fd , buf , & st , flags , enc ) == 0 )
29803032 new_pathtype = IFTODT (st .st_mode );
29813033 else
29823034 new_pathtype = path_noent ;
@@ -3532,7 +3584,7 @@ dir_foreach(int argc, VALUE *argv, VALUE io)
35323584}
35333585
35343586static VALUE
3535- dir_entry_ary_push (VALUE ary , VALUE entry , unsigned char ftype )
3587+ dir_entry_ary_push (VALUE ary , VALUE entry , struct dir_entry_args * _unused )
35363588{
35373589 return rb_ary_push (ary , entry );
35383590}
@@ -3935,16 +3987,16 @@ Init_Dir(void)
39353987 sym_file = ID2SYM (rb_intern ("file" ));
39363988 sym_unknown = ID2SYM (rb_intern ("unknown" ));
39373989
3938- #ifdef DT_BLK
3990+ #if defined( DT_BLK ) || defined( S_IFBLK )
39393991 sym_block_device = ID2SYM (rb_intern ("blockSpecial" ));
39403992#endif
3941- #ifdef DT_CHR
3993+ #if defined( DT_CHR ) || defined( S_IFCHR )
39423994 sym_character_device = ID2SYM (rb_intern ("characterSpecial" ));
39433995#endif
3944- #ifdef DT_FIFO
3996+ #if defined( DT_FIFO ) || defined( S_IFIFO )
39453997 sym_fifo = ID2SYM (rb_intern ("fifo" ));
39463998#endif
3947- #ifdef DT_SOCK
3999+ #if defined( DT_SOCK ) || defined( S_IFSOCK )
39484000 sym_socket = ID2SYM (rb_intern ("socket" ));
39494001#endif
39504002
0 commit comments