@@ -14,7 +14,8 @@ use os::unix::prelude::*;
14
14
use ffi:: { CString , CStr , OsString , OsStr } ;
15
15
use fmt;
16
16
use 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} ;
18
19
use mem;
19
20
use path:: { Path , PathBuf } ;
20
21
use ptr;
@@ -43,7 +44,7 @@ unsafe impl Send for Dir {}
43
44
unsafe impl Sync for Dir { }
44
45
45
46
pub struct DirEntry {
46
- buf : Vec < u8 > , // actually *mut libc:: dirent
47
+ entry : dirent ,
47
48
root : Arc < PathBuf > ,
48
49
}
49
50
@@ -126,32 +127,22 @@ impl Iterator for ReadDir {
126
127
type Item = io:: Result < DirEntry > ;
127
128
128
129
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 ( ) ,
149
133
root : self . root . clone ( )
150
134
} ;
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
+ }
155
146
}
156
147
}
157
148
}
@@ -166,7 +157,7 @@ impl Drop for Dir {
166
157
167
158
impl DirEntry {
168
159
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 ( ) ) )
170
161
}
171
162
172
163
pub fn file_name ( & self ) -> OsString {
@@ -178,35 +169,64 @@ impl DirEntry {
178
169
}
179
170
180
171
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 ( ) ) ,
189
181
}
190
182
}
191
183
184
+ #[ cfg( any( target_os = "macos" ,
185
+ target_os = "ios" ,
186
+ target_os = "linux" ) ) ]
192
187
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
197
203
}
198
204
205
+ #[ cfg( any( target_os = "macos" ,
206
+ target_os = "ios" ,
207
+ target_os = "netbsd" ) ) ]
199
208
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 )
202
212
}
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 ] {
203
219
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 )
205
222
}
206
223
}
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
+ }
210
230
}
211
231
}
212
232
0 commit comments