Skip to content

Commit e783959

Browse files
committed
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
1 parent cd1661d commit e783959

File tree

1 file changed

+40
-9
lines changed

1 file changed

+40
-9
lines changed

src/libstd/os.rs

+40-9
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ pub fn self_exe_path() -> Option<Path> {
503503
* 'USERPROFILE' environment variable if it is set and not equal to the empty
504504
* string.
505505
*
506-
* Otherwise, homedir returns option::none.
506+
* Otherwise, homedir returns `None`.
507507
*/
508508
pub fn homedir() -> Option<Path> {
509509
// FIXME (#7188): getenv needs a ~[u8] variant
@@ -627,7 +627,7 @@ pub fn path_exists(p: &Path) -> bool {
627627
}
628628

629629
/**
630-
* Convert a relative path to an absolute path
630+
* Converts a relative path to an absolute path
631631
*
632632
* If the given path is relative, return it prepended with the current working
633633
* 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 {
676676
}
677677

678678
/// Creates a directory with a given mode.
679-
/// Returns true iff creation
679+
/// Returns `true` iff creation
680680
/// succeeded. Also creates all intermediate subdirectories
681681
/// if they don't already exist, giving all of them the same mode.
682682
@@ -788,11 +788,9 @@ pub fn list_dir(p: &Path) -> ~[Path] {
788788
}
789789
}
790790

791-
/**
792-
* Lists the contents of a directory
793-
*
794-
* This version prepends each entry with the directory.
795-
*/
791+
/// Lists the contents of a directory
792+
///
793+
/// This version prepends each entry with the directory.
796794
pub fn list_dir_path(p: &Path) -> ~[Path] {
797795
list_dir(p).map(|f| p.join(f))
798796
}
@@ -873,8 +871,26 @@ pub fn change_dir(p: &Path) -> bool {
873871
}
874872
}
875873

876-
/// Copies a file from one location to another
874+
/**
875+
* Copies a file from one location to another
876+
*
877+
* Returns `false` if the destination path exists, or if the source path is not
878+
* a file.
879+
*
880+
* Note: this does not protect against concurrent systems which may create the
881+
* destination before the file is copied, but after is it checked not to exist.
882+
*/
877883
pub fn copy_file(from: &Path, to: &Path) -> bool {
884+
if to.exists() {
885+
return false;
886+
}
887+
888+
// Only proceed if `from` is a file
889+
match from.stat() {
890+
Some(st) => if !st.is_file { return false; },
891+
None => ()
892+
}
893+
878894
return do_copy_file(from, to);
879895

880896
#[cfg(windows)]
@@ -2007,6 +2023,21 @@ mod tests {
20072023
}
20082024
}
20092025

2026+
#[test]
2027+
fn copy_file_destination_exists() {
2028+
let tempdir = getcwd();
2029+
let input = tempdir.join("in.txt");
2030+
let out = tempdir.join("in.txt"); // Same as above.
2031+
assert!(!os::copy_file(&input, &out));
2032+
}
2033+
2034+
#[test]
2035+
fn copy_file_source_is_dir() {
2036+
let tempdir = getcwd();
2037+
let out = tempdir.join("out.txt");
2038+
assert!(!os::copy_file(&tempdir, &out));
2039+
}
2040+
20102041
#[test]
20112042
fn recursive_mkdir_slash() {
20122043
let path = Path::new("/");

0 commit comments

Comments
 (0)