From e78395946649bea635c85464f9211064fec67436 Mon Sep 17 00:00:00 2001 From: Ziad Hatahet Date: Wed, 30 Oct 2013 09:02:15 -0700 Subject: [PATCH] Modifications to os::copy_file() * Returns `false` if destination exists. * Returns `false` if source is not a file (e.g. dir, sym link, etc.). cc #9947 --- src/libstd/os.rs | 49 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 1f32c6a0a35ef..5b1935f80505a 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -503,7 +503,7 @@ pub fn self_exe_path() -> Option { * 'USERPROFILE' environment variable if it is set and not equal to the empty * string. * - * Otherwise, homedir returns option::none. + * Otherwise, homedir returns `None`. */ pub fn homedir() -> Option { // FIXME (#7188): getenv needs a ~[u8] variant @@ -627,7 +627,7 @@ pub fn path_exists(p: &Path) -> bool { } /** - * Convert a relative path to an absolute path + * Converts a relative path to an absolute path * * If the given path is relative, return it prepended with the current working * directory. If the given path is already an absolute path, return it @@ -676,7 +676,7 @@ pub fn make_dir(p: &Path, mode: c_int) -> bool { } /// Creates a directory with a given mode. -/// Returns true iff creation +/// Returns `true` iff creation /// succeeded. Also creates all intermediate subdirectories /// if they don't already exist, giving all of them the same mode. @@ -788,11 +788,9 @@ pub fn list_dir(p: &Path) -> ~[Path] { } } -/** - * Lists the contents of a directory - * - * This version prepends each entry with the directory. - */ +/// Lists the contents of a directory +/// +/// This version prepends each entry with the directory. pub fn list_dir_path(p: &Path) -> ~[Path] { list_dir(p).map(|f| p.join(f)) } @@ -873,8 +871,26 @@ pub fn change_dir(p: &Path) -> bool { } } -/// Copies a file from one location to another +/** + * Copies a file from one location to another + * + * Returns `false` if the destination path exists, or if the source path is not + * a file. + * + * Note: this does not protect against concurrent systems which may create the + * destination before the file is copied, but after is it checked not to exist. + */ pub fn copy_file(from: &Path, to: &Path) -> bool { + if to.exists() { + return false; + } + + // Only proceed if `from` is a file + match from.stat() { + Some(st) => if !st.is_file { return false; }, + None => () + } + return do_copy_file(from, to); #[cfg(windows)] @@ -2007,6 +2023,21 @@ mod tests { } } + #[test] + fn copy_file_destination_exists() { + let tempdir = getcwd(); + let input = tempdir.join("in.txt"); + let out = tempdir.join("in.txt"); // Same as above. + assert!(!os::copy_file(&input, &out)); + } + + #[test] + fn copy_file_source_is_dir() { + let tempdir = getcwd(); + let out = tempdir.join("out.txt"); + assert!(!os::copy_file(&tempdir, &out)); + } + #[test] fn recursive_mkdir_slash() { let path = Path::new("/");