summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Keller <philipp.keller@gmail.com>2016-09-02 22:57:39 +0200
committerPhilipp Keller <philipp.keller@gmail.com>2016-09-02 22:57:39 +0200
commitac642737967525226dc36f43e6e99d58328d5c6c (patch)
tree8883b813e519ef1bf208b876bb8d0ccd80a8a3ed
parent07039357d8d519ab1fe3591b9f9b05fd49ab4195 (diff)
downloadnix-ac642737967525226dc36f43e6e99d58328d5c6c.zip
implemented getcwd (returning Result<PathBuf>, reconciling all calls to expect into proper try handling), needs testing still
-rw-r--r--src/unistd.rs42
-rw-r--r--test/test_unistd.rs5
2 files changed, 46 insertions, 1 deletions
diff --git a/src/unistd.rs b/src/unistd.rs
index d4da60da..34e9b6a9 100644
--- a/src/unistd.rs
+++ b/src/unistd.rs
@@ -5,9 +5,10 @@ use fcntl::{fcntl, OFlag, O_NONBLOCK, O_CLOEXEC, FD_CLOEXEC};
use fcntl::FcntlArg::{F_SETFD, F_SETFL};
use libc::{self, c_char, c_void, c_int, c_uint, size_t, pid_t, off_t, uid_t, gid_t};
use std::mem;
-use std::ffi::CString;
+use std::ffi::{CString,CStr};
use std::os::unix::io::RawFd;
use void::Void;
+use std::path::PathBuf;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub use self::linux::*;
@@ -111,6 +112,45 @@ pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
Errno::result(res).map(drop)
}
+// #[inline]
+// pub fn mkdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
+// Errno::result(0)
+// }
+
+#[inline]
+pub fn getcwd() -> Result<PathBuf> {
+ let mut buf = Vec::with_capacity(512);
+ loop {
+ unsafe {
+ let ptr = buf.as_mut_ptr() as *mut libc::c_char;
+
+ // The buffer must be large enough to store the absolute pathname plus
+ // a terminating null byte, or else null is returned.
+ // To safely handle this we start with a reasonable size (512 bytes)
+ // and double the buffer size upon every error
+ if !libc::getcwd(ptr, buf.capacity()).is_null() {
+ let len = CStr::from_ptr(ptr).to_bytes().len();
+ buf.set_len(len);
+ buf.shrink_to_fit();
+ let s = try!(CString::new(buf).map_err(|_| Error::Sys(Errno::EILSEQ)));
+ let s = try!(s.into_string().map_err(|_| Error::Sys(Errno::EILSEQ)));
+ return Ok(PathBuf::from(&s));
+ } else {
+ let error = Errno::last();
+ if error == Errno::ERANGE {
+ return Err(Error::Sys(error));
+ }
+ }
+
+ // 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);
+ }
+ }
+}
+
#[inline]
pub fn chown<P: ?Sized + NixPath>(path: &P, owner: Option<uid_t>, group: Option<gid_t>) -> Result<()> {
let res = try!(path.with_nix_path(|cstr| {
diff --git a/test/test_unistd.rs b/test/test_unistd.rs
index 188bfbeb..48891bc3 100644
--- a/test/test_unistd.rs
+++ b/test/test_unistd.rs
@@ -120,6 +120,11 @@ macro_rules! execve_test_factory(
);
#[test]
+fn test_getcwd() {
+ println!("{}", getcwd().unwrap().display());
+}
+
+#[test]
fn test_lseek() {
const CONTENTS: &'static [u8] = b"abcdef123456";
let mut tmp = tempfile().unwrap();