Skip to content

Commit d045ce7

Browse files
committed
core: Use a better termination condition in os::mkdir_recursive
Instead of checking whether the parent is "." or "/", check the number of components. Also, more tests.
1 parent 379dce1 commit d045ce7

File tree

2 files changed

+79
-22
lines changed

2 files changed

+79
-22
lines changed

src/libcore/os.rs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -643,20 +643,22 @@ pub fn make_dir(p: &Path, mode: c_int) -> bool {
643643
/// Returns true iff creation
644644
/// succeeded. Also creates all intermediate subdirectories
645645
/// if they don't already exist, giving all of them the same mode.
646+
647+
// tjc: if directory exists but with different permissions,
648+
// should we return false?
646649
pub fn mkdir_recursive(p: &Path, mode: c_int) -> bool {
647650
if path_is_dir(p) {
648651
return true;
649652
}
650-
let parent = p.dir_path();
651-
debug!("mkdir_recursive: parent = %s",
652-
parent.to_str());
653-
if parent.to_str() == ~"."
654-
|| parent.to_str() == ~"/" { // !!!
653+
else if p.components.is_empty() {
654+
return false;
655+
}
656+
else if p.components.len() == 1 {
655657
// No parent directories to create
656-
path_is_dir(&parent) && make_dir(p, mode)
658+
path_is_dir(p) || make_dir(p, mode)
657659
}
658660
else {
659-
mkdir_recursive(&parent, mode) && make_dir(p, mode)
661+
mkdir_recursive(&p.pop(), mode) && make_dir(p, mode)
660662
}
661663
}
662664

@@ -1267,6 +1269,8 @@ mod tests {
12671269
use run;
12681270
use str;
12691271
use vec;
1272+
use libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
1273+
12701274
12711275
#[test]
12721276
pub fn last_os_error() {
@@ -1490,16 +1494,16 @@ mod tests {
14901494
}
14911495
14921496
#[test]
1493-
fn recursive_mkdir_ok() {
1494-
use libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
1497+
fn recursive_mkdir_slash() {
1498+
let path = Path("/");
1499+
assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
1500+
}
14951501
1496-
let root = os::tmpdir();
1497-
let path = "xy/z/zy";
1498-
let nested = root.push(path);
1499-
assert!(os::mkdir_recursive(&nested, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
1500-
assert!(os::path_is_dir(&root.push("xy")));
1501-
assert!(os::path_is_dir(&root.push("xy/z")));
1502-
assert!(os::path_is_dir(&nested));
1502+
#[test]
1503+
fn recursive_mkdir_empty() {
1504+
let path = Path("");
1505+
assert!(!os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
15031506
}
15041507

1508+
// More recursive_mkdir tests are in std::tempfile
15051509
}

src/libstd/tempfile.rs

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,62 @@ pub fn mkdtemp(tmpdir: &Path, suffix: &str) -> Option<Path> {
2323
None
2424
}
2525

26-
#[test]
27-
fn test_mkdtemp() {
28-
let p = mkdtemp(&Path("."), "foobar").unwrap();
29-
os::remove_dir(&p);
30-
assert!(str::ends_with(p.to_str(), "foobar"));
31-
}
26+
#[cfg(test)]
27+
mod tests {
28+
use tempfile::mkdtemp;
29+
use tempfile;
30+
31+
#[test]
32+
fn test_mkdtemp() {
33+
let p = mkdtemp(&Path("."), "foobar").unwrap();
34+
os::remove_dir(&p);
35+
assert!(str::ends_with(p.to_str(), "foobar"));
36+
}
37+
38+
// Ideally these would be in core::os but then core would need
39+
// to depend on std
40+
#[test]
41+
fn recursive_mkdir_rel() {
42+
use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
43+
use core::os;
44+
45+
let root = mkdtemp(&os::tmpdir(), "temp").expect("recursive_mkdir_rel");
46+
os::change_dir(&root);
47+
let path = Path("frob");
48+
assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
49+
assert!(os::path_is_dir(&path));
50+
assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
51+
assert!(os::path_is_dir(&path));
52+
}
53+
54+
#[test]
55+
fn recursive_mkdir_dot() {
56+
use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
57+
use core::os;
58+
59+
let dot = Path(".");
60+
assert!(os::mkdir_recursive(&dot, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
61+
let dotdot = Path("..");
62+
assert!(os::mkdir_recursive(&dotdot, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
63+
}
64+
65+
#[test]
66+
fn recursive_mkdir_rel_2() {
67+
use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
68+
use core::os;
69+
70+
let root = mkdtemp(&os::tmpdir(), "temp").expect("recursive_mkdir_rel_2");
71+
os::change_dir(&root);
72+
let path = Path("./frob/baz");
73+
debug!("...Making: %s in cwd %s", path.to_str(), os::getcwd().to_str());
74+
assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
75+
assert!(os::path_is_dir(&path));
76+
assert!(os::path_is_dir(&path.pop()));
77+
let path2 = Path("quux/blat");
78+
debug!("Making: %s in cwd %s", path2.to_str(), os::getcwd().to_str());
79+
assert!(os::mkdir_recursive(&path2, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
80+
assert!(os::path_is_dir(&path2));
81+
assert!(os::path_is_dir(&path2.pop()));
82+
}
83+
84+
}

0 commit comments

Comments
 (0)