summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOtavio Salvador <otavio@ossystems.com.br>2019-09-21 18:56:00 -0300
committerOtavio Salvador <otavio@ossystems.com.br>2019-09-21 18:56:00 -0300
commit035c69f9957778a9002679d800ec6dff8a778996 (patch)
tree89d3d93e3dc749a02cec2c0f5a5d57793794b076
parentac5de6b1a91f09851f3b2b46fd5b85a63167247e (diff)
downloadnix-035c69f9957778a9002679d800ec6dff8a778996.zip
unistd: getcwd: Double the buffer when need, up to PATH_MAX as limit
We now have a `reserve_double_buffer_size` method which reserves the double of buffer, up to a limit, allowing it to be reused on other methods in future. Signed-off-by: Otavio Salvador <otavio@ossystems.com.br>
-rw-r--r--src/unistd.rs24
1 files changed, 18 insertions, 6 deletions
diff --git a/src/unistd.rs b/src/unistd.rs
index 4dca01b9..ea22f38e 100644
--- a/src/unistd.rs
+++ b/src/unistd.rs
@@ -5,7 +5,7 @@ use {Error, Result, NixPath};
use fcntl::{AtFlags, at_rawfd, fcntl, FdFlag, OFlag};
use fcntl::FcntlArg::F_SETFD;
use libc::{self, c_char, c_void, c_int, c_long, c_uint, size_t, pid_t, off_t,
- uid_t, gid_t, mode_t};
+ uid_t, gid_t, mode_t, PATH_MAX};
use std::{fmt, mem, ptr};
use std::ffi::{CString, CStr, OsString, OsStr};
use std::os::unix::ffi::{OsStringExt, OsStrExt};
@@ -534,6 +534,21 @@ pub fn symlinkat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
Errno::result(res).map(drop)
}
+// Double the buffer capacity up to limit. In case it already has
+// reached the limit, return Errno::ERANGE.
+fn reserve_double_buffer_size<T>(buf: &mut Vec<T>, limit: usize) -> Result<()> {
+ use std::cmp::min;
+
+ if buf.len() >= limit {
+ return Err(Error::Sys(Errno::ERANGE))
+ }
+
+ let capacity = min(buf.capacity() * 2, limit);
+ buf.reserve(capacity);
+
+ Ok(())
+}
+
/// Returns the current directory as a `PathBuf`
///
/// Err is returned if the current user doesn't have the permission to read or search a component
@@ -576,11 +591,8 @@ pub fn getcwd() -> Result<PathBuf> {
}
}
- // Trigger the internal buffer resizing logic of `Vec` by requiring
- // more space than the current capacity.
- let cap = buf.capacity();
- buf.set_len(cap);
- buf.reserve(1);
+ // Trigger the internal buffer resizing logic.
+ reserve_double_buffer_size(&mut buf, PATH_MAX as usize)?;
}
}
}