@@ -51,6 +51,7 @@ fs::unlink(&path);
51
51
52
52
use c_str:: ToCStr ;
53
53
use clone:: Clone ;
54
+ use container:: Container ;
54
55
use iter:: Iterator ;
55
56
use super :: { Reader , Writer , Seek } ;
56
57
use super :: { SeekStyle , Read , Write , Open , IoError , Truncate ,
@@ -62,6 +63,7 @@ use result::{Ok, Err};
62
63
use path;
63
64
use path:: { Path , GenericPath } ;
64
65
use vec:: { OwnedVector , ImmutableVector } ;
66
+ use vec_ng:: Vec ;
65
67
66
68
/// Unconstrained file access type that exposes read and write operations
67
69
///
@@ -557,16 +559,47 @@ pub fn mkdir_recursive(path: &Path, mode: FilePermission) -> IoResult<()> {
557
559
/// This function will return an `Err` value if an error happens. See
558
560
/// `file::unlink` and `fs::readdir` for possible error conditions.
559
561
pub fn rmdir_recursive ( path : & Path ) -> IoResult < ( ) > {
560
- let children = try!( readdir ( path) ) ;
561
- for child in children. iter ( ) {
562
- if child. is_dir ( ) {
563
- try!( rmdir_recursive ( child) ) ;
564
- } else {
565
- try!( unlink ( child) ) ;
562
+ let mut rm_stack = Vec :: new ( ) ;
563
+ rm_stack. push ( path. clone ( ) ) ;
564
+
565
+ while !rm_stack. is_empty ( ) {
566
+ let children = try!( readdir ( rm_stack. last ( ) . unwrap ( ) ) ) ;
567
+ let mut has_child_dir = false ;
568
+
569
+ // delete all regular files in the way and push subdirs
570
+ // on the stack
571
+ for child in children. move_iter ( ) {
572
+ // FIXME(#12795) we should use lstat in all cases
573
+ let child_type = match cfg ! ( windows) {
574
+ true => try!( stat ( & child) ) . kind ,
575
+ false => try!( lstat ( & child) ) . kind
576
+ } ;
577
+
578
+ if child_type == io:: TypeDirectory {
579
+ rm_stack. push ( child) ;
580
+ has_child_dir = true ;
581
+ } else {
582
+ // we can carry on safely if the file is already gone
583
+ // (eg: deleted by someone else since readdir)
584
+ match unlink ( & child) {
585
+ Ok ( ( ) ) => ( ) ,
586
+ Err ( ref e) if e. kind == io:: FileNotFound => ( ) ,
587
+ Err ( e) => return Err ( e)
588
+ }
589
+ }
590
+ }
591
+
592
+ // if no subdir was found, let's pop and delete
593
+ if !has_child_dir {
594
+ match rmdir ( & rm_stack. pop ( ) . unwrap ( ) ) {
595
+ Ok ( ( ) ) => ( ) ,
596
+ Err ( ref e) if e. kind == io:: FileNotFound => ( ) ,
597
+ Err ( e) => return Err ( e)
598
+ }
566
599
}
567
600
}
568
- // Directory should now be empty
569
- rmdir ( path )
601
+
602
+ Ok ( ( ) )
570
603
}
571
604
572
605
/// Changes the timestamps for a file's last modification and access time.
0 commit comments