@@ -900,14 +900,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
900900 }
901901 }
902902
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 > {
908904 let this = self . eval_context_mut ( ) ;
909905
910- if !matches ! ( & * this. tcx. sess. target. os, "linux" | "solaris" | "illumos" ) {
906+ if !matches ! ( & * this. tcx. sess. target. os, "linux" | "solaris" | "illumos" | "freebsd" ) {
911907 panic ! ( "`linux_solaris_readdir64` should not be called on {}" , this. tcx. sess. target. os) ;
912908 }
913909
@@ -926,6 +922,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
926922
927923 let entry = match open_dir. read_dir . next ( ) {
928924 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+
929932 // Write the directory entry into a newly allocated buffer.
930933 // The name is written with write_bytes, while the rest of the
931934 // dirent64 (or dirent) struct is written using write_int_fields.
@@ -947,6 +950,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
947950 // pub d_reclen: c_ushort,
948951 // pub d_name: [c_char; 3],
949952 // }
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+ // }
950962
951963 let mut name = dir_entry. file_name ( ) ; // not a Path as there are no separators!
952964 name. push ( "\0 " ) ; // Add a NUL terminator
@@ -965,31 +977,35 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
965977 MiriMemoryKind :: Runtime . into ( ) ,
966978 AllocInit :: Uninit ,
967979 ) ?;
968- let entry: Pointer = entry. into ( ) ;
980+ let entry = this . ptr_to_mplace ( entry. into ( ) , dirent_layout ) ;
969981
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" } ;
978985 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,
981988 ) ?;
982989
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" ) ? {
9861001 this. write_int ( file_type, & d_type) ?;
9871002 }
9881003
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) ;
9901006 this. write_bytes_ptr ( name_ptr, name_bytes. iter ( ) . copied ( ) ) ?;
9911007
992- Some ( entry)
1008+ Some ( entry. ptr ( ) )
9931009 }
9941010 None => {
9951011 // end of stream: return NULL
0 commit comments