@@ -35,7 +35,7 @@ pub struct FileAttr {
35
35
36
36
#[ derive( Copy , Clone , PartialEq , Eq , Hash ) ]
37
37
pub enum FileType {
38
- Dir , File , Symlink , ReparsePoint , MountPoint ,
38
+ Dir , File , SymlinkFile , SymlinkDir , ReparsePoint , MountPoint ,
39
39
}
40
40
41
41
pub struct ReadDir {
@@ -444,23 +444,30 @@ impl FilePermissions {
444
444
445
445
impl FileType {
446
446
fn new ( attrs : c:: DWORD , reparse_tag : c:: DWORD ) -> FileType {
447
- if attrs & c:: FILE_ATTRIBUTE_REPARSE_POINT != 0 {
448
- match reparse_tag {
449
- c:: IO_REPARSE_TAG_SYMLINK => FileType :: Symlink ,
450
- c:: IO_REPARSE_TAG_MOUNT_POINT => FileType :: MountPoint ,
451
- _ => FileType :: ReparsePoint ,
452
- }
453
- } else if attrs & c:: FILE_ATTRIBUTE_DIRECTORY != 0 {
454
- FileType :: Dir
455
- } else {
456
- FileType :: File
447
+ match ( attrs & c:: FILE_ATTRIBUTE_DIRECTORY != 0 ,
448
+ attrs & c:: FILE_ATTRIBUTE_REPARSE_POINT != 0 ,
449
+ reparse_tag) {
450
+ ( false , false , _) => FileType :: File ,
451
+ ( true , false , _) => FileType :: Dir ,
452
+ ( false , true , c:: IO_REPARSE_TAG_SYMLINK ) => FileType :: SymlinkFile ,
453
+ ( true , true , c:: IO_REPARSE_TAG_SYMLINK ) => FileType :: SymlinkDir ,
454
+ ( true , true , c:: IO_REPARSE_TAG_MOUNT_POINT ) => FileType :: MountPoint ,
455
+ ( _, true , _) => FileType :: ReparsePoint ,
456
+ // Note: if a _file_ has a reparse tag of the type IO_REPARSE_TAG_MOUNT_POINT it is
457
+ // invalid, as junctions always have to be dirs. We set the filetype to ReparsePoint
458
+ // to indicate it is something symlink-like, but not something you can follow.
457
459
}
458
460
}
459
461
460
462
pub fn is_dir ( & self ) -> bool { * self == FileType :: Dir }
461
463
pub fn is_file ( & self ) -> bool { * self == FileType :: File }
462
464
pub fn is_symlink ( & self ) -> bool {
463
- * self == FileType :: Symlink || * self == FileType :: MountPoint
465
+ * self == FileType :: SymlinkFile ||
466
+ * self == FileType :: SymlinkDir ||
467
+ * self == FileType :: MountPoint
468
+ }
469
+ pub fn is_symlink_dir ( & self ) -> bool {
470
+ * self == FileType :: SymlinkDir || * self == FileType :: MountPoint
464
471
}
465
472
}
466
473
@@ -519,18 +526,14 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
519
526
520
527
pub fn remove_dir_all ( path : & Path ) -> io:: Result < ( ) > {
521
528
for child in try!( readdir ( path) ) {
522
- let child = try!( child) . path ( ) ;
523
- let stat = try!( lstat ( & * child) ) ;
524
- if stat. data . dwFileAttributes & c:: FILE_ATTRIBUTE_DIRECTORY != 0 {
525
- if stat. data . dwFileAttributes & c:: FILE_ATTRIBUTE_REPARSE_POINT != 0 {
526
- // remove junctions and directory symlinks with rmdir
527
- try!( rmdir ( & * child) ) ;
528
- } else {
529
- try!( remove_dir_all ( & * child) ) ;
530
- }
529
+ let child = try!( child) ;
530
+ let child_type = try!( child. file_type ( ) ) ;
531
+ if child_type. is_dir ( ) {
532
+ try!( remove_dir_all ( & child. path ( ) ) ) ;
533
+ } else if child_type. is_symlink_dir ( ) {
534
+ try!( rmdir ( & child. path ( ) ) ) ;
531
535
} else {
532
- // remove files and file symlinks
533
- try!( unlink ( & * child) ) ;
536
+ try!( unlink ( & child. path ( ) ) ) ;
534
537
}
535
538
}
536
539
rmdir ( path)
0 commit comments