@@ -35,7 +35,7 @@ pub struct FileAttr {
3535
3636#[ derive( Copy , Clone , PartialEq , Eq , Hash ) ]
3737pub enum FileType {
38- Dir , File , Symlink , ReparsePoint , MountPoint ,
38+ Dir , File , SymlinkFile , SymlinkDir , ReparsePoint , MountPoint ,
3939}
4040
4141pub struct ReadDir {
@@ -444,23 +444,30 @@ impl FilePermissions {
444444
445445impl FileType {
446446 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.
457459 }
458460 }
459461
460462 pub fn is_dir ( & self ) -> bool { * self == FileType :: Dir }
461463 pub fn is_file ( & self ) -> bool { * self == FileType :: File }
462464 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
464471 }
465472}
466473
@@ -519,18 +526,14 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
519526
520527pub fn remove_dir_all ( path : & Path ) -> io:: Result < ( ) > {
521528 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 ( ) ) ) ;
531535 } else {
532- // remove files and file symlinks
533- try!( unlink ( & * child) ) ;
536+ try!( unlink ( & child. path ( ) ) ) ;
534537 }
535538 }
536539 rmdir ( path)
0 commit comments