diff options
| author | Barosl Lee <vcs@barosl.com> | 2014-11-11 14:38:20 +0900 |
|---|---|---|
| committer | Barosl Lee <vcs@barosl.com> | 2014-11-19 05:31:45 +0900 |
| commit | 6f422c4c05f4d108ba6429a174aa0c2ef3b183fa (patch) | |
| tree | b393a680897f0d6a80b96f1fda5c6fcb636f8cc5 /src/libstd | |
| parent | 09e2ad13d0aa01143bcb20dece3ff6c5a7e34ea3 (diff) | |
| download | rust-6f422c4c05f4d108ba6429a174aa0c2ef3b183fa.tar.gz rust-6f422c4c05f4d108ba6429a174aa0c2ef3b183fa.zip | |
Make os::getcwd() return IoResult<Path>
os::getcwd() panics if the current directory is not available. According to getcwd(3), there are three cases: - EACCES: Permission denied. - ENOENT: The current working directory has been removed. - ERANGE: The buffer size is less than the actual absolute path. This commit makes os::getcwd() return IoResult<Path>, not just Path, preventing it from panicking. As os::make_absolute() depends on os::getcwd(), it is also modified to return IoResult<Path>. Fixes #16946. [breaking-change]
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/io/process.rs | 4 | ||||
| -rw-r--r-- | src/libstd/io/tempfile.rs | 3 | ||||
| -rw-r--r-- | src/libstd/io/test.rs | 2 | ||||
| -rw-r--r-- | src/libstd/os.rs | 64 |
4 files changed, 43 insertions, 30 deletions
diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs index 16e568f30f2..592ec0681a9 100644 --- a/src/libstd/io/process.rs +++ b/src/libstd/io/process.rs @@ -974,7 +974,7 @@ mod tests { let prog = pwd_cmd().spawn().unwrap(); let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap(); - let parent_dir = os::getcwd(); + let parent_dir = os::getcwd().unwrap(); let child_dir = Path::new(output.as_slice().trim()); let parent_stat = parent_dir.stat().unwrap(); @@ -989,7 +989,7 @@ mod tests { use os; // test changing to the parent of os::getcwd() because we know // the path exists (and os::getcwd() is not expected to be root) - let parent_dir = os::getcwd().dir_path(); + let parent_dir = os::getcwd().unwrap().dir_path(); let prog = pwd_cmd().cwd(&parent_dir).spawn().unwrap(); let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap(); diff --git a/src/libstd/io/tempfile.rs b/src/libstd/io/tempfile.rs index e9d6ef2e341..a232231733d 100644 --- a/src/libstd/io/tempfile.rs +++ b/src/libstd/io/tempfile.rs @@ -35,7 +35,8 @@ impl TempDir { /// If no directory can be created, `Err` is returned. pub fn new_in(tmpdir: &Path, suffix: &str) -> IoResult<TempDir> { if !tmpdir.is_absolute() { - return TempDir::new_in(&os::make_absolute(tmpdir), suffix); + let abs_tmpdir = try!(os::make_absolute(tmpdir)); + return TempDir::new_in(&abs_tmpdir, suffix); } static CNT: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; diff --git a/src/libstd/io/test.rs b/src/libstd/io/test.rs index 6571dc41585..a153ead2a38 100644 --- a/src/libstd/io/test.rs +++ b/src/libstd/io/test.rs @@ -75,7 +75,7 @@ fn base_port() -> u16 { ]; // FIXME (#9639): This needs to handle non-utf8 paths - let path = os::getcwd(); + let path = os::getcwd().unwrap(); let path_s = path.as_str().unwrap(); let mut final_base = base; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index f7afce9f409..971138c06fb 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -38,7 +38,7 @@ pub use self::MapError::*; use clone::Clone; use error::{FromError, Error}; use fmt; -use io::IoResult; +use io::{IoResult, IoError}; use iter::Iterator; use libc::{c_void, c_int}; use libc; @@ -76,15 +76,16 @@ pub fn num_cpus() -> uint { pub const TMPBUF_SZ : uint = 1000u; const BUF_BYTES : uint = 2048u; -/// Returns the current working directory as a Path. +/// Returns the current working directory as a `Path`. /// -/// # Failure +/// # Errors /// -/// Fails if the current working directory value is invalid: +/// Returns an `Err` if the current working directory value is invalid. /// Possible cases: /// /// * Current directory does not exist. /// * There are insufficient permissions to access the current directory. +/// * The internal buffer is not large enough to hold the path. /// /// # Example /// @@ -92,32 +93,34 @@ const BUF_BYTES : uint = 2048u; /// use std::os; /// /// // We assume that we are in a valid directory like "/home". -/// let current_working_directory = os::getcwd(); +/// let current_working_directory = os::getcwd().unwrap(); /// println!("The current directory is {}", current_working_directory.display()); /// // /home /// ``` #[cfg(unix)] -pub fn getcwd() -> Path { +pub fn getcwd() -> IoResult<Path> { use c_str::CString; let mut buf = [0 as c_char, ..BUF_BYTES]; unsafe { if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() { - panic!() + Err(IoError::last_error()) + } else { + Ok(Path::new(CString::new(buf.as_ptr(), false))) } - Path::new(CString::new(buf.as_ptr(), false)) } } -/// Returns the current working directory as a Path. +/// Returns the current working directory as a `Path`. /// -/// # Failure +/// # Errors /// -/// Fails if the current working directory value is invalid. -/// Possibles cases: +/// Returns an `Err` if the current working directory value is invalid. +/// Possible cases: /// /// * Current directory does not exist. /// * There are insufficient permissions to access the current directory. +/// * The internal buffer is not large enough to hold the path. /// /// # Example /// @@ -125,23 +128,31 @@ pub fn getcwd() -> Path { /// use std::os; /// /// // We assume that we are in a valid directory like "C:\\Windows". -/// let current_working_directory = os::getcwd(); +/// let current_working_directory = os::getcwd().unwrap(); /// println!("The current directory is {}", current_working_directory.display()); /// // C:\\Windows /// ``` #[cfg(windows)] -pub fn getcwd() -> Path { +pub fn getcwd() -> IoResult<Path> { use libc::DWORD; use libc::GetCurrentDirectoryW; + use io::OtherIoError; let mut buf = [0 as u16, ..BUF_BYTES]; unsafe { if libc::GetCurrentDirectoryW(buf.len() as DWORD, buf.as_mut_ptr()) == 0 as DWORD { - panic!(); + return Err(IoError::last_error()); } } - Path::new(String::from_utf16(::str::truncate_utf16_at_nul(&buf)) - .expect("GetCurrentDirectoryW returned invalid UTF-16")) + + match String::from_utf16(::str::truncate_utf16_at_nul(&buf)) { + Some(ref cwd) => Ok(Path::new(cwd)), + None => Err(IoError { + kind: OtherIoError, + desc: "GetCurrentDirectoryW returned invalid UTF-16", + detail: None, + }), + } } #[cfg(windows)] @@ -829,20 +840,21 @@ pub fn tmpdir() -> Path { /// /// // Assume we're in a path like /home/someuser /// let rel_path = Path::new(".."); -/// let abs_path = os::make_absolute(&rel_path); +/// let abs_path = os::make_absolute(&rel_path).unwrap(); /// println!("The absolute path is {}", abs_path.display()); /// // Prints "The absolute path is /home" /// ``` // NB: this is here rather than in path because it is a form of environment // querying; what it does depends on the process working directory, not just // the input paths. -pub fn make_absolute(p: &Path) -> Path { +pub fn make_absolute(p: &Path) -> IoResult<Path> { if p.is_absolute() { - p.clone() + Ok(p.clone()) } else { - let mut ret = getcwd(); - ret.push(p); - ret + getcwd().map(|mut cwd| { + cwd.push(p); + cwd + }) } } @@ -1881,11 +1893,11 @@ mod tests { fn test() { assert!((!Path::new("test-path").is_absolute())); - let cwd = getcwd(); + let cwd = getcwd().unwrap(); debug!("Current working directory: {}", cwd.display()); - debug!("{}", make_absolute(&Path::new("test-path")).display()); - debug!("{}", make_absolute(&Path::new("/usr/bin")).display()); + debug!("{}", make_absolute(&Path::new("test-path")).unwrap().display()); + debug!("{}", make_absolute(&Path::new("/usr/bin")).unwrap().display()); } #[test] |
