summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/unistd.rs20
-rw-r--r--test/test_unistd.rs15
2 files changed, 27 insertions, 8 deletions
diff --git a/src/unistd.rs b/src/unistd.rs
index 34e9b6a9..f8e17153 100644
--- a/src/unistd.rs
+++ b/src/unistd.rs
@@ -3,12 +3,13 @@
use {Errno, Error, Result, NixPath};
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 libc::{self, c_char, c_void, c_int, c_uint, size_t, pid_t, off_t, uid_t, gid_t, mode_t};
use std::mem;
use std::ffi::{CString,CStr};
+use std::path::PathBuf;
use std::os::unix::io::RawFd;
use void::Void;
-use std::path::PathBuf;
+use sys::stat::Mode;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub use self::linux::*;
@@ -112,10 +113,14 @@ 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 mkdir<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
+ let res = try!(path.with_nix_path(|cstr| {
+ unsafe { libc::mkdir(cstr.as_ptr(), mode.bits() as mode_t) }
+ }));
+
+ Errno::result(res).map(drop)
+}
#[inline]
pub fn getcwd() -> Result<PathBuf> {
@@ -137,7 +142,8 @@ pub fn getcwd() -> Result<PathBuf> {
return Ok(PathBuf::from(&s));
} else {
let error = Errno::last();
- if error == Errno::ERANGE {
+ // ERANGE means buffer was too small to store directory name
+ if error != Errno::ERANGE {
return Err(Error::Sys(error));
}
}
diff --git a/test/test_unistd.rs b/test/test_unistd.rs
index 2b6182b6..26746426 100644
--- a/test/test_unistd.rs
+++ b/test/test_unistd.rs
@@ -3,6 +3,8 @@ extern crate tempdir;
use nix::unistd::*;
use nix::unistd::ForkResult::*;
use nix::sys::wait::*;
+use nix::sys::stat;
+use std::iter;
use std::ffi::CString;
use std::io::{Write, Read};
@@ -129,7 +131,18 @@ fn test_getcwd() {
} else {
"/tmp/"
};
- let tmp_dir = TempDir::new_in(base, "test_getcwd").expect("create temp dir").into_path();
+ let mut tmp_dir = TempDir::new_in(base, "test_getcwd").expect("create temp dir").into_path();
+ assert!(chdir(tmp_dir.as_path()).is_ok());
+ assert_eq!(getcwd().unwrap(), tmp_dir);
+
+ // make path 500 chars longer so that buffer doubling in getcwd kicks in.
+ // Note: One path cannot be longer than 255 bytes (NAME_MAX)
+ // whole path cannot be longer than PATH_MAX (usually 4096 on linux, 1024 on macos)
+ for _ in 0..5 {
+ let newdir = iter::repeat("a").take(100).collect::<String>();
+ tmp_dir.push(newdir);
+ assert!(mkdir(tmp_dir.as_path(), stat::S_IRWXU).is_ok());
+ }
assert!(chdir(tmp_dir.as_path()).is_ok());
assert_eq!(getcwd().unwrap(), tmp_dir);
}