@@ -900,14 +900,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
900
900
}
901
901
}
902
902
903
- fn linux_solarish_readdir64 (
904
- & mut self ,
905
- dirent_type : & str ,
906
- dirp_op : & OpTy < ' tcx > ,
907
- ) -> InterpResult < ' tcx , Scalar > {
903
+ fn readdir64 ( & mut self , dirent_type : & str , dirp_op : & OpTy < ' tcx > ) -> InterpResult < ' tcx , Scalar > {
908
904
let this = self . eval_context_mut ( ) ;
909
905
910
- if !matches ! ( & * this. tcx. sess. target. os, "linux" | "solaris" | "illumos" ) {
906
+ if !matches ! ( & * this. tcx. sess. target. os, "linux" | "solaris" | "illumos" | "freebsd" ) {
911
907
panic ! ( "`linux_solaris_readdir64` should not be called on {}" , this. tcx. sess. target. os) ;
912
908
}
913
909
@@ -926,6 +922,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
926
922
927
923
let entry = match open_dir. read_dir . next ( ) {
928
924
Some ( Ok ( dir_entry) ) => {
925
+ // If the host is a Unix system, fill in the inode number with its real value.
926
+ // If not, use 0 as a fallback value.
927
+ #[ cfg( unix) ]
928
+ let ino = std:: os:: unix:: fs:: DirEntryExt :: ino ( & dir_entry) ;
929
+ #[ cfg( not( unix) ) ]
930
+ let ino = 0u64 ;
931
+
929
932
// Write the directory entry into a newly allocated buffer.
930
933
// The name is written with write_bytes, while the rest of the
931
934
// dirent64 (or dirent) struct is written using write_int_fields.
@@ -947,6 +950,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
947
950
// pub d_reclen: c_ushort,
948
951
// pub d_name: [c_char; 3],
949
952
// }
953
+ //
954
+ // On FreeBSD:
955
+ // pub struct dirent{
956
+ // pub d_fileno: uint32_t,
957
+ // pub d_reclen: uint16_t,
958
+ // pub d_type: uint8_t,
959
+ // pub d_namlen: uint8_t,
960
+ // pub d_name: [c_char; 256]
961
+ // }
950
962
951
963
let mut name = dir_entry. file_name ( ) ; // not a Path as there are no separators!
952
964
name. push ( "\0 " ) ; // Add a NUL terminator
@@ -965,31 +977,35 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
965
977
MiriMemoryKind :: Runtime . into ( ) ,
966
978
AllocInit :: Uninit ,
967
979
) ?;
968
- let entry: Pointer = entry. into ( ) ;
980
+ let entry = this . ptr_to_mplace ( entry. into ( ) , dirent_layout ) ;
969
981
970
- // If the host is a Unix system, fill in the inode number with its real value.
971
- // If not, use 0 as a fallback value.
972
- #[ cfg( unix) ]
973
- let ino = std:: os:: unix:: fs:: DirEntryExt :: ino ( & dir_entry) ;
974
- #[ cfg( not( unix) ) ]
975
- let ino = 0u64 ;
976
-
977
- let file_type = this. file_type_to_d_type ( dir_entry. file_type ( ) ) ?;
982
+ // Write common fields
983
+ let ino_name =
984
+ if this. tcx . sess . target . os == "freebsd" { "d_fileno" } else { "d_ino" } ;
978
985
this. write_int_fields_named (
979
- & [ ( "d_ino" , ino. into ( ) ) , ( "d_off" , 0 ) , ( "d_reclen" , size. into ( ) ) ] ,
980
- & this . ptr_to_mplace ( entry, dirent_layout ) ,
986
+ & [ ( ino_name , ino. into ( ) ) , ( "d_reclen" , size. into ( ) ) ] ,
987
+ & entry,
981
988
) ?;
982
989
983
- if let Some ( d_type) = this
984
- . try_project_field_named ( & this. ptr_to_mplace ( entry, dirent_layout) , "d_type" ) ?
985
- {
990
+ // Write "optional" fields.
991
+ if let Some ( d_off) = this. try_project_field_named ( & entry, "d_off" ) ? {
992
+ this. write_null ( & d_off) ?;
993
+ }
994
+
995
+ if let Some ( d_namlen) = this. try_project_field_named ( & entry, "d_namlen" ) ? {
996
+ this. write_int ( name_len. strict_sub ( 1 ) , & d_namlen) ?;
997
+ }
998
+
999
+ let file_type = this. file_type_to_d_type ( dir_entry. file_type ( ) ) ?;
1000
+ if let Some ( d_type) = this. try_project_field_named ( & entry, "d_type" ) ? {
986
1001
this. write_int ( file_type, & d_type) ?;
987
1002
}
988
1003
989
- let name_ptr = entry. wrapping_offset ( Size :: from_bytes ( d_name_offset) , this) ;
1004
+ // The name is not a normal field, we already computed the offset above.
1005
+ let name_ptr = entry. ptr ( ) . wrapping_offset ( Size :: from_bytes ( d_name_offset) , this) ;
990
1006
this. write_bytes_ptr ( name_ptr, name_bytes. iter ( ) . copied ( ) ) ?;
991
1007
992
- Some ( entry)
1008
+ Some ( entry. ptr ( ) )
993
1009
}
994
1010
None => {
995
1011
// end of stream: return NULL
0 commit comments