Skip to content

Commit fe0b5c0

Browse files
committed
Auto merge of #26896 - tbu-:pr_getcwd, r=alexcrichton
(On Windows, it works already.)
2 parents fddfd08 + b83ec47 commit fe0b5c0

File tree

2 files changed

+26
-20
lines changed

2 files changed

+26
-20
lines changed

src/libstd/env.rs

-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ use sys::os as os_imp;
3636
///
3737
/// * Current directory does not exist.
3838
/// * There are insufficient permissions to access the current directory.
39-
/// * The internal buffer is not large enough to hold the path.
4039
///
4140
/// # Examples
4241
///

src/libstd/sys/unix/os.rs

+26-19
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,17 @@ use io;
2222
use iter;
2323
use libc::{self, c_int, c_char, c_void};
2424
use mem;
25-
use ptr;
2625
use path::{self, PathBuf};
26+
use ptr;
2727
use slice;
2828
use str;
2929
use sys::c;
3030
use sys::fd;
3131
use vec;
3232

33-
const BUF_BYTES: usize = 2048;
33+
const GETCWD_BUF_BYTES: usize = 2048;
3434
const TMPBUF_SZ: usize = 128;
3535

36-
fn bytes2path(b: &[u8]) -> PathBuf {
37-
PathBuf::from(<OsStr as OsStrExt>::from_bytes(b))
38-
}
39-
40-
fn os2path(os: OsString) -> PathBuf {
41-
bytes2path(os.as_bytes())
42-
}
43-
4436
/// Returns the platform-specific value of errno
4537
pub fn errno() -> i32 {
4638
#[cfg(any(target_os = "macos",
@@ -102,12 +94,24 @@ pub fn error_string(errno: i32) -> String {
10294
}
10395

10496
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()))
97+
let mut buf = Vec::new();
98+
let mut n = GETCWD_BUF_BYTES;
99+
loop {
100+
unsafe {
101+
buf.reserve(n);
102+
let ptr = buf.as_mut_ptr() as *mut libc::c_char;
103+
if !libc::getcwd(ptr, buf.capacity() as libc::size_t).is_null() {
104+
let len = CStr::from_ptr(buf.as_ptr() as *const libc::c_char).to_bytes().len();
105+
buf.set_len(len);
106+
buf.shrink_to_fit();
107+
return Ok(PathBuf::from(OsString::from_vec(buf)));
108+
} else {
109+
let error = io::Error::last_os_error();
110+
if error.raw_os_error() != Some(libc::ERANGE) {
111+
return Err(error);
112+
}
113+
}
114+
n *= 2;
111115
}
112116
}
113117
}
@@ -129,11 +133,14 @@ pub struct SplitPaths<'a> {
129133
}
130134

131135
pub fn split_paths<'a>(unparsed: &'a OsStr) -> SplitPaths<'a> {
136+
fn bytes_to_path(b: &[u8]) -> PathBuf {
137+
PathBuf::from(<OsStr as OsStrExt>::from_bytes(b))
138+
}
132139
fn is_colon(b: &u8) -> bool { *b == b':' }
133140
let unparsed = unparsed.as_bytes();
134141
SplitPaths {
135142
iter: unparsed.split(is_colon as fn(&u8) -> bool)
136-
.map(bytes2path as fn(&'a [u8]) -> PathBuf)
143+
.map(bytes_to_path as fn(&'a [u8]) -> PathBuf)
137144
}
138145
}
139146

@@ -444,7 +451,7 @@ pub fn page_size() -> usize {
444451
}
445452

446453
pub fn temp_dir() -> PathBuf {
447-
getenv("TMPDIR".as_ref()).map(os2path).unwrap_or_else(|| {
454+
getenv("TMPDIR".as_ref()).map(PathBuf::from).unwrap_or_else(|| {
448455
if cfg!(target_os = "android") {
449456
PathBuf::from("/data/local/tmp")
450457
} else {
@@ -456,7 +463,7 @@ pub fn temp_dir() -> PathBuf {
456463
pub fn home_dir() -> Option<PathBuf> {
457464
return getenv("HOME".as_ref()).or_else(|| unsafe {
458465
fallback()
459-
}).map(os2path);
466+
}).map(PathBuf::from);
460467

461468
#[cfg(any(target_os = "android",
462469
target_os = "ios"))]

0 commit comments

Comments
 (0)