@@ -14,7 +14,8 @@ use os::unix::prelude::*;
1414use ffi:: { CString , CStr , OsString , OsStr } ;
1515use fmt;
1616use io:: { self , Error , ErrorKind , SeekFrom } ;
17- use libc:: { self , c_int, off_t, c_char, mode_t} ;
17+ use libc:: { dirent, readdir_r} ;
18+ use libc:: { self , c_int, off_t, mode_t} ;
1819use mem;
1920use path:: { Path , PathBuf } ;
2021use ptr;
@@ -43,7 +44,7 @@ unsafe impl Send for Dir {}
4344unsafe impl Sync for Dir { }
4445
4546pub struct DirEntry {
46- buf : Vec < u8 > , // actually *mut libc:: dirent
47+ entry : dirent ,
4748 root : Arc < PathBuf > ,
4849}
4950
@@ -126,32 +127,22 @@ impl Iterator for ReadDir {
126127 type Item = io:: Result < DirEntry > ;
127128
128129 fn next ( & mut self ) -> Option < io:: Result < DirEntry > > {
129- extern {
130- fn rust_dirent_t_size ( ) -> libc:: size_t ;
131- }
132-
133- let mut buf: Vec < u8 > = Vec :: with_capacity ( unsafe {
134- rust_dirent_t_size ( )
135- } ) ;
136- let ptr = buf. as_mut_ptr ( ) as * mut libc:: dirent ;
137-
138- let mut entry_ptr = ptr:: null_mut ( ) ;
139- loop {
140- if unsafe { libc:: readdir_r ( self . dirp . 0 , ptr, & mut entry_ptr) != 0 } {
141- return Some ( Err ( Error :: last_os_error ( ) ) )
142- }
143- if entry_ptr. is_null ( ) {
144- return None
145- }
146-
147- let entry = DirEntry {
148- buf : buf,
130+ unsafe {
131+ let mut ret = DirEntry {
132+ entry : mem:: zeroed ( ) ,
149133 root : self . root . clone ( )
150134 } ;
151- if entry. name_bytes ( ) == b"." || entry. name_bytes ( ) == b".." {
152- buf = entry. buf ;
153- } else {
154- return Some ( Ok ( entry) )
135+ let mut entry_ptr = ptr:: null_mut ( ) ;
136+ loop {
137+ if readdir_r ( self . dirp . 0 , & mut ret. entry , & mut entry_ptr) != 0 {
138+ return Some ( Err ( Error :: last_os_error ( ) ) )
139+ }
140+ if entry_ptr. is_null ( ) {
141+ return None
142+ }
143+ if ret. name_bytes ( ) != b"." && ret. name_bytes ( ) != b".." {
144+ return Some ( Ok ( ret) )
145+ }
155146 }
156147 }
157148 }
@@ -166,7 +157,7 @@ impl Drop for Dir {
166157
167158impl DirEntry {
168159 pub fn path ( & self ) -> PathBuf {
169- self . root . join ( < OsStr as OsStrExt > :: from_bytes ( self . name_bytes ( ) ) )
160+ self . root . join ( OsStr :: from_bytes ( self . name_bytes ( ) ) )
170161 }
171162
172163 pub fn file_name ( & self ) -> OsString {
@@ -178,35 +169,64 @@ impl DirEntry {
178169 }
179170
180171 pub fn file_type ( & self ) -> io:: Result < FileType > {
181- extern {
182- fn rust_dir_get_mode ( ptr : * mut libc:: dirent ) -> c_int ;
183- }
184- unsafe {
185- match rust_dir_get_mode ( self . dirent ( ) ) {
186- -1 => lstat ( & self . path ( ) ) . map ( |m| m. file_type ( ) ) ,
187- n => Ok ( FileType { mode : n as mode_t } ) ,
188- }
172+ match self . entry . d_type {
173+ libc:: DT_CHR => Ok ( FileType { mode : libc:: S_IFCHR } ) ,
174+ libc:: DT_FIFO => Ok ( FileType { mode : libc:: S_IFIFO } ) ,
175+ libc:: DT_LNK => Ok ( FileType { mode : libc:: S_IFLNK } ) ,
176+ libc:: DT_REG => Ok ( FileType { mode : libc:: S_IFREG } ) ,
177+ libc:: DT_SOCK => Ok ( FileType { mode : libc:: S_IFSOCK } ) ,
178+ libc:: DT_DIR => Ok ( FileType { mode : libc:: S_IFDIR } ) ,
179+ libc:: DT_BLK => Ok ( FileType { mode : libc:: S_IFBLK } ) ,
180+ _ => lstat ( & self . path ( ) ) . map ( |m| m. file_type ( ) ) ,
189181 }
190182 }
191183
184+ #[ cfg( any( target_os = "macos" ,
185+ target_os = "ios" ,
186+ target_os = "linux" ) ) ]
192187 pub fn ino ( & self ) -> raw:: ino_t {
193- extern {
194- fn rust_dir_get_ino ( ptr : * mut libc:: dirent ) -> raw:: ino_t ;
195- }
196- unsafe { rust_dir_get_ino ( self . dirent ( ) ) }
188+ self . entry . d_ino
189+ }
190+
191+ #[ cfg( target_os = "android" ) ]
192+ pub fn ino ( & self ) -> raw:: ino_t {
193+ self . entry . d_ino as raw:: ino_t
194+ }
195+
196+ #[ cfg( any( target_os = "freebsd" ,
197+ target_os = "openbsd" ,
198+ target_os = "bitrig" ,
199+ target_os = "netbsd" ,
200+ target_os = "dragonfly" ) ) ]
201+ pub fn ino ( & self ) -> raw:: ino_t {
202+ self . entry . d_fileno
197203 }
198204
205+ #[ cfg( any( target_os = "macos" ,
206+ target_os = "ios" ,
207+ target_os = "netbsd" ) ) ]
199208 fn name_bytes ( & self ) -> & [ u8 ] {
200- extern {
201- fn rust_list_dir_val ( ptr : * mut libc:: dirent ) -> * const c_char ;
209+ unsafe {
210+ :: slice:: from_raw_parts ( self . entry . d_name . as_ptr ( ) as * const u8 ,
211+ self . entry . d_namlen as usize )
202212 }
213+ }
214+ #[ cfg( any( target_os = "freebsd" ,
215+ target_os = "dragonfly" ,
216+ target_os = "bitrig" ,
217+ target_os = "openbsd" ) ) ]
218+ fn name_bytes ( & self ) -> & [ u8 ] {
203219 unsafe {
204- CStr :: from_ptr ( rust_list_dir_val ( self . dirent ( ) ) ) . to_bytes ( )
220+ :: slice:: from_raw_parts ( self . entry . d_name . as_ptr ( ) as * const u8 ,
221+ self . entry . d_namelen as usize )
205222 }
206223 }
207-
208- fn dirent ( & self ) -> * mut libc:: dirent {
209- self . buf . as_ptr ( ) as * mut _
224+ #[ cfg( any( target_os = "android" ,
225+ target_os = "linux" ) ) ]
226+ fn name_bytes ( & self ) -> & [ u8 ] {
227+ unsafe {
228+ CStr :: from_ptr ( self . entry . d_name . as_ptr ( ) ) . to_bytes ( )
229+ }
210230 }
211231}
212232
0 commit comments