Skip to content
44 changes: 27 additions & 17 deletions library/std/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3333,26 +3333,36 @@ impl DirBuilder {
return Ok(());
}

match self.inner.mkdir(path) {
Ok(()) => return Ok(()),
Err(ref e) if e.kind() == io::ErrorKind::NotFound => {}
Err(_) if path.is_dir() => return Ok(()),
Err(e) => return Err(e),
}
match path.parent() {
Some(p) => self.create_dir_all(p)?,
None => {
return Err(io::const_error!(
io::ErrorKind::Uncategorized,
"failed to create whole tree",
));
let ancestors = path.ancestors();
let mut uncreated_dir_ctr = 0;

for ancestor in ancestors {
if ancestor == Path::new("") {
break;
}

match self.inner.mkdir(ancestor) {
Ok(()) => break,
Err(e) if e.kind() == io::ErrorKind::NotFound => uncreated_dir_ctr += 1,
// we check if the err is AlreadyExists for two reasons
// - in case the path exists as a *file*
// - and to avoid calls to .is_dir() in case of other errs
// (i.e. PermissionDenied)
Err(e) if e.kind() == io::ErrorKind::AlreadyExists && ancestor.is_dir() => break,
Err(e) => return Err(e),
}
}
match self.inner.mkdir(path) {
Ok(()) => Ok(()),
Err(_) if path.is_dir() => Ok(()),
Err(e) => Err(e),

let uncreated_dirs: Box<[_]> = ancestors.take(uncreated_dir_ctr).collect();
for uncreated_dir in uncreated_dirs.iter().rev() {
if let Err(e) = self.inner.mkdir(uncreated_dir) {
if !uncreated_dir.is_dir() {
return Err(e);
}
}
}

Ok(())
}
}

Expand Down
Loading