File tree 3 files changed +49
-10
lines changed 3 files changed +49
-10
lines changed Original file line number Diff line number Diff line change @@ -36,7 +36,6 @@ use sys::os as os_imp;
36
36
///
37
37
/// * Current directory does not exist.
38
38
/// * There are insufficient permissions to access the current directory.
39
- /// * The internal buffer is not large enough to hold the path.
40
39
///
41
40
/// # Examples
42
41
///
Original file line number Diff line number Diff line change @@ -75,6 +75,41 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
75
75
}
76
76
}
77
77
78
+ // Some system functions expect the user to pass a appropiately-sized buffer
79
+ // without specifying its size. They will only report back whether the buffer
80
+ // was large enough or not.
81
+ //
82
+ // The callback is yielded a (pointer, len) pair which can be
83
+ // passed to a syscall. The `ptr` is valid for `len` items (i8 in this case).
84
+ // The closure is expected to return `None` if the space was insufficient and
85
+ // `Some(r)` if the syscall did not fail due to insufficient space.
86
+ fn fill_bytes_buf < F , T > ( mut f : F ) -> io:: Result < T >
87
+ where F : FnMut ( * mut i8 , libc:: size_t ) -> Option < io:: Result < T > > ,
88
+ {
89
+ // Start off with a stack buf but then spill over to the heap if we end up
90
+ // needing more space.
91
+ let mut stack_buf = [ 0i8 ; os:: BUF_BYTES ] ;
92
+ let mut heap_buf = Vec :: new ( ) ;
93
+ unsafe {
94
+ let mut n = stack_buf. len ( ) ;
95
+ loop {
96
+ let buf = if n <= stack_buf. len ( ) {
97
+ & mut stack_buf[ ..]
98
+ } else {
99
+ heap_buf. set_len ( 0 ) ;
100
+ heap_buf. reserve ( n) ;
101
+ heap_buf. set_len ( n) ;
102
+ & mut heap_buf[ ..]
103
+ } ;
104
+
105
+ match f ( buf. as_mut_ptr ( ) , n as libc:: size_t ) {
106
+ None => n *= 2 ,
107
+ Some ( r) => return r,
108
+ }
109
+ }
110
+ }
111
+ }
112
+
78
113
pub fn cvt < T : One + PartialEq + Neg < Output =T > > ( t : T ) -> io:: Result < T > {
79
114
let one: T = T :: one ( ) ;
80
115
if t == -one {
Original file line number Diff line number Diff line change @@ -22,15 +22,15 @@ use io;
22
22
use iter;
23
23
use libc:: { self , c_int, c_char, c_void} ;
24
24
use mem;
25
- use ptr;
26
25
use path:: { self , PathBuf } ;
26
+ use ptr;
27
27
use slice;
28
28
use str;
29
29
use sys:: c;
30
30
use sys:: fd;
31
31
use vec;
32
32
33
- const BUF_BYTES : usize = 2048 ;
33
+ pub const BUF_BYTES : usize = 2048 ;
34
34
const TMPBUF_SZ : usize = 128 ;
35
35
36
36
fn bytes2path ( b : & [ u8 ] ) -> PathBuf {
@@ -102,14 +102,19 @@ pub fn error_string(errno: i32) -> String {
102
102
}
103
103
104
104
pub fn getcwd ( ) -> io:: Result < PathBuf > {
105
- let mut buf = [ 0 as c_char ; BUF_BYTES ] ;
106
- unsafe {
107
- if libc:: getcwd ( buf. as_mut_ptr ( ) , buf. len ( ) as libc:: size_t ) . is_null ( ) {
108
- Err ( io:: Error :: last_os_error ( ) )
109
- } else {
110
- Ok ( bytes2path ( CStr :: from_ptr ( buf. as_ptr ( ) ) . to_bytes ( ) ) )
105
+ super :: fill_bytes_buf ( |buf, len| {
106
+ unsafe {
107
+ Some ( if !libc:: getcwd ( buf, len) . is_null ( ) {
108
+ Ok ( bytes2path ( CStr :: from_ptr ( buf) . to_bytes ( ) ) )
109
+ } else {
110
+ let error = io:: Error :: last_os_error ( ) ;
111
+ if error. raw_os_error ( ) . unwrap ( ) == libc:: ERANGE {
112
+ return None ;
113
+ }
114
+ Err ( error)
115
+ } )
111
116
}
112
- }
117
+ } )
113
118
}
114
119
115
120
pub fn chdir ( p : & path:: Path ) -> io:: Result < ( ) > {
You can’t perform that action at this time.
0 commit comments