From b1b9edf5ae3c6a8a862e480174f9fefafeba7143 Mon Sep 17 00:00:00 2001 From: Peter Atashian Date: Thu, 1 Feb 2018 20:18:33 -0500 Subject: This is what FileType on Windows should ideally be. --- src/libstd/sys/windows/fs.rs | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 165e1b0609b..001e7ceeb71 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -38,8 +38,9 @@ pub struct FileAttr { } #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -pub enum FileType { - Dir, File, SymlinkFile, SymlinkDir, ReparsePoint, MountPoint, +pub struct FileType { + attributes: c::DWORD, + reparse_tag: c::DWORD, } pub struct ReadDir { @@ -516,30 +517,28 @@ impl FilePermissions { impl FileType { fn new(attrs: c::DWORD, reparse_tag: c::DWORD) -> FileType { - match (attrs & c::FILE_ATTRIBUTE_DIRECTORY != 0, - attrs & c::FILE_ATTRIBUTE_REPARSE_POINT != 0, - reparse_tag) { - (false, false, _) => FileType::File, - (true, false, _) => FileType::Dir, - (false, true, c::IO_REPARSE_TAG_SYMLINK) => FileType::SymlinkFile, - (true, true, c::IO_REPARSE_TAG_SYMLINK) => FileType::SymlinkDir, - (true, true, c::IO_REPARSE_TAG_MOUNT_POINT) => FileType::MountPoint, - (_, true, _) => FileType::ReparsePoint, - // Note: if a _file_ has a reparse tag of the type IO_REPARSE_TAG_MOUNT_POINT it is - // invalid, as junctions always have to be dirs. We set the filetype to ReparsePoint - // to indicate it is something symlink-like, but not something you can follow. + FileType { + attributes: attrs, + reparse_tag: reparse_tag, } } - pub fn is_dir(&self) -> bool { *self == FileType::Dir } - pub fn is_file(&self) -> bool { *self == FileType::File } + pub fn is_dir(&self) -> bool { + self.attributes & c::FILE_ATTRIBUTE_DIRECTORY != 0 + } + pub fn is_file(&self) -> bool { + self.attributes & c::FILE_ATTRIBUTE_DIRECTORY == 0 + } pub fn is_symlink(&self) -> bool { - *self == FileType::SymlinkFile || - *self == FileType::SymlinkDir || - *self == FileType::MountPoint + self.is_reparse_point() && ( + self.reparse_tag == c::IO_REPARSE_TAG_SYMLINK || + self.reparse_tag == c::IO_REPARSE_TAG_MOUNT_POINT) } pub fn is_symlink_dir(&self) -> bool { - *self == FileType::SymlinkDir || *self == FileType::MountPoint + self.is_symlink() && self.is_dir() + } + pub fn is_reparse_point(&self) -> bool { + self.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 } } -- cgit 1.4.1-3-g733a5 From dcf53c1590b741a16e92c7e5a306e923827ae301 Mon Sep 17 00:00:00 2001 From: Peter Atashian Date: Thu, 1 Feb 2018 20:35:50 -0500 Subject: Rewrite remove_dir_all to be correct The fact that this had to be rewritten does not bode well --- src/libstd/sys/windows/fs.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 001e7ceeb71..87a09925313 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -611,9 +611,11 @@ fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { let child = child?; let child_type = child.file_type()?; if child_type.is_dir() { - remove_dir_all_recursive(&child.path())?; - } else if child_type.is_symlink_dir() { - rmdir(&child.path())?; + if child_type.is_reparse_point() { + rmdir(&child.path())?; + } else { + remove_dir_all_recursive(&child.path())?; + } } else { unlink(&child.path())?; } -- cgit 1.4.1-3-g733a5 From 259b0329d42ea9ce971c0c8c9ff72f8496a73b9e Mon Sep 17 00:00:00 2001 From: Peter Atashian Date: Thu, 1 Feb 2018 20:42:31 -0500 Subject: This internal only method is no longer needed. --- src/libstd/sys/windows/fs.rs | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 87a09925313..a49c3569b02 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -534,9 +534,6 @@ impl FileType { self.reparse_tag == c::IO_REPARSE_TAG_SYMLINK || self.reparse_tag == c::IO_REPARSE_TAG_MOUNT_POINT) } - pub fn is_symlink_dir(&self) -> bool { - self.is_symlink() && self.is_dir() - } pub fn is_reparse_point(&self) -> bool { self.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 } -- cgit 1.4.1-3-g733a5 From f4c83693f9e2445b441dfcf43838697d25d1a11f Mon Sep 17 00:00:00 2001 From: Peter Atashian Date: Sat, 3 Feb 2018 01:45:58 -0500 Subject: Go back to files directories and symlinks being mutually exclusive Be smarter about what a symlink is however --- src/libstd/sys/windows/fs.rs | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index a49c3569b02..512c9cb838c 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -522,21 +522,27 @@ impl FileType { reparse_tag: reparse_tag, } } - pub fn is_dir(&self) -> bool { - self.attributes & c::FILE_ATTRIBUTE_DIRECTORY != 0 + !self.is_symlink() && self.is_directory() } pub fn is_file(&self) -> bool { - self.attributes & c::FILE_ATTRIBUTE_DIRECTORY == 0 + !self.is_symlink() && !self.is_directory() } pub fn is_symlink(&self) -> bool { - self.is_reparse_point() && ( - self.reparse_tag == c::IO_REPARSE_TAG_SYMLINK || - self.reparse_tag == c::IO_REPARSE_TAG_MOUNT_POINT) + self.is_reparse_point() && self.is_reparse_tag_name_surrogate() + } + pub fn is_symlink_dir(&self) -> bool { + self.is_symlink() && self.is_directory() + } + fn is_directory(&self) -> bool { + self.attributes & c::FILE_ATTRIBUTE_DIRECTORY != 0 } - pub fn is_reparse_point(&self) -> bool { + fn is_reparse_point(&self) -> bool { self.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 } + fn is_reparse_tag_name_surrogate(&self) -> bool { + self.reparse_tag & 0x20000000 != 0 + } } impl DirBuilder { @@ -607,12 +613,10 @@ fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { for child in readdir(path)? { let child = child?; let child_type = child.file_type()?; - if child_type.is_dir() { - if child_type.is_reparse_point() { - rmdir(&child.path())?; - } else { - remove_dir_all_recursive(&child.path())?; - } + if child_type.is_symlink_dir() { + rmdir(&child.path())?; + } else if child_type.is_dir() { + remove_dir_all_recursive(&child.path())?; } else { unlink(&child.path())?; } -- cgit 1.4.1-3-g733a5 From c42d76d3c80b4938e26e628706363b677fde6ca1 Mon Sep 17 00:00:00 2001 From: Peter Atashian Date: Sat, 3 Feb 2018 01:52:04 -0500 Subject: Somehow this function got flipped around Unflip it --- src/libstd/sys/windows/fs.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 512c9cb838c..7e3b16558d4 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -613,10 +613,10 @@ fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { for child in readdir(path)? { let child = child?; let child_type = child.file_type()?; - if child_type.is_symlink_dir() { - rmdir(&child.path())?; - } else if child_type.is_dir() { + if child_type.is_dir() { remove_dir_all_recursive(&child.path())?; + } else if child_type.is_symlink_dir() { + rmdir(&child.path())?; } else { unlink(&child.path())?; } -- cgit 1.4.1-3-g733a5 From 9269e83b37e8e5fd9cef12255fafbc6db6220035 Mon Sep 17 00:00:00 2001 From: Peter Atashian Date: Sun, 11 Feb 2018 13:40:46 -0500 Subject: Add an unstable FileTypeExt extension trait for Windows --- src/libstd/sys/windows/ext/fs.rs | 18 ++++++++++++++++++ src/libstd/sys/windows/fs.rs | 3 +++ 2 files changed, 21 insertions(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index 24c41046f26..38bf4cca851 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -445,6 +445,24 @@ impl MetadataExt for Metadata { fn file_size(&self) -> u64 { self.as_inner().size() } } +/// Add support for the Windows specific fact that a symbolic link knows whether it is a file +/// or directory. +#[unstable(feature = "windows_file_type_ext", issue = "0")] +pub trait FileTypeExt { + /// Returns whether this file type is a symbolic link that is also a directory. + #[unstable(feature = "windows_file_type_ext", issue = "0")] + fn is_symlink_dir(&self) -> bool; + /// Returns whether this file type is a symbolic link that is also a file. + #[unstable(feature = "windows_file_type_ext", issue = "0")] + fn is_symlink_file(&self) -> bool; +} + +#[unstable(feature = "windows_file_type_ext", issue = "0")] +impl FileTypeExt for fs::FileType { + fn is_symlink_dir(&self) -> bool { self.as_inner().is_symlink_dir() } + fn is_symlink_file(&self) -> bool { self.as_inner().is_symlink_file() } +} + /// Creates a new file symbolic link on the filesystem. /// /// The `dst` path will be a file symbolic link pointing to the `src` diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 7e3b16558d4..082d4689c7b 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -534,6 +534,9 @@ impl FileType { pub fn is_symlink_dir(&self) -> bool { self.is_symlink() && self.is_directory() } + pub fn is_symlink_file(&self) -> bool { + self.is_symlink() && !self.is_directory() + } fn is_directory(&self) -> bool { self.attributes & c::FILE_ATTRIBUTE_DIRECTORY != 0 } -- cgit 1.4.1-3-g733a5