diff options
Diffstat (limited to 'vendor/same-file/src/win.rs')
| -rw-r--r-- | vendor/same-file/src/win.rs | 172 |
1 files changed, 0 insertions, 172 deletions
diff --git a/vendor/same-file/src/win.rs b/vendor/same-file/src/win.rs deleted file mode 100644 index 69247399..00000000 --- a/vendor/same-file/src/win.rs +++ /dev/null @@ -1,172 +0,0 @@ -use std::fs::File; -use std::hash::{Hash, Hasher}; -use std::io; -use std::os::windows::io::{AsRawHandle, IntoRawHandle, RawHandle}; -use std::path::Path; - -use winapi_util as winutil; - -// For correctness, it is critical that both file handles remain open while -// their attributes are checked for equality. In particular, the file index -// numbers on a Windows stat object are not guaranteed to remain stable over -// time. -// -// See the docs and remarks on MSDN: -// https://msdn.microsoft.com/en-us/library/windows/desktop/aa363788(v=vs.85).aspx -// -// It gets worse. It appears that the index numbers are not always -// guaranteed to be unique. Namely, ReFS uses 128 bit numbers for unique -// identifiers. This requires a distinct syscall to get `FILE_ID_INFO` -// documented here: -// https://msdn.microsoft.com/en-us/library/windows/desktop/hh802691(v=vs.85).aspx -// -// It seems straight-forward enough to modify this code to use -// `FILE_ID_INFO` when available (minimum Windows Server 2012), but I don't -// have access to such Windows machines. -// -// Two notes. -// -// 1. Java's NIO uses the approach implemented here and appears to ignore -// `FILE_ID_INFO` altogether. So Java's NIO and this code are -// susceptible to bugs when running on a file system where -// `nFileIndex{Low,High}` are not unique. -// -// 2. LLVM has a bug where they fetch the id of a file and continue to use -// it even after the handle has been closed, so that uniqueness is no -// longer guaranteed (when `nFileIndex{Low,High}` are unique). -// bug report: http://lists.llvm.org/pipermail/llvm-bugs/2014-December/037218.html -// -// All said and done, checking whether two files are the same on Windows -// seems quite tricky. Moreover, even if the code is technically incorrect, -// it seems like the chances of actually observing incorrect behavior are -// extremely small. Nevertheless, we mitigate this by checking size too. -// -// In the case where this code is erroneous, two files will be reported -// as equivalent when they are in fact distinct. This will cause the loop -// detection code to report a false positive, which will prevent descending -// into the offending directory. As far as failure modes goes, this isn't -// that bad. - -#[derive(Debug)] -pub struct Handle { - kind: HandleKind, - key: Option<Key>, -} - -#[derive(Debug)] -enum HandleKind { - /// Used when opening a file or acquiring ownership of a file. - Owned(winutil::Handle), - /// Used for stdio. - Borrowed(winutil::HandleRef), -} - -#[derive(Debug, Eq, PartialEq, Hash)] -struct Key { - volume: u64, - index: u64, -} - -impl Eq for Handle {} - -impl PartialEq for Handle { - fn eq(&self, other: &Handle) -> bool { - // Need this branch to satisfy `Eq` since `Handle`s with - // `key.is_none()` wouldn't otherwise. - if self as *const Handle == other as *const Handle { - return true; - } else if self.key.is_none() || other.key.is_none() { - return false; - } - self.key == other.key - } -} - -impl AsRawHandle for crate::Handle { - fn as_raw_handle(&self) -> RawHandle { - match self.0.kind { - HandleKind::Owned(ref h) => h.as_raw_handle(), - HandleKind::Borrowed(ref h) => h.as_raw_handle(), - } - } -} - -impl IntoRawHandle for crate::Handle { - fn into_raw_handle(self) -> RawHandle { - match self.0.kind { - HandleKind::Owned(h) => h.into_raw_handle(), - HandleKind::Borrowed(h) => h.as_raw_handle(), - } - } -} - -impl Hash for Handle { - fn hash<H: Hasher>(&self, state: &mut H) { - self.key.hash(state); - } -} - -impl Handle { - pub fn from_path<P: AsRef<Path>>(p: P) -> io::Result<Handle> { - let h = winutil::Handle::from_path_any(p)?; - let info = winutil::file::information(&h)?; - Ok(Handle::from_info(HandleKind::Owned(h), info)) - } - - pub fn from_file(file: File) -> io::Result<Handle> { - let h = winutil::Handle::from_file(file); - let info = winutil::file::information(&h)?; - Ok(Handle::from_info(HandleKind::Owned(h), info)) - } - - fn from_std_handle(h: winutil::HandleRef) -> io::Result<Handle> { - match winutil::file::information(&h) { - Ok(info) => Ok(Handle::from_info(HandleKind::Borrowed(h), info)), - // In a Windows console, if there is no pipe attached to a STD - // handle, then GetFileInformationByHandle will return an error. - // We don't really care. The only thing we care about is that - // this handle is never equivalent to any other handle, which is - // accomplished by setting key to None. - Err(_) => Ok(Handle { kind: HandleKind::Borrowed(h), key: None }), - } - } - - fn from_info( - kind: HandleKind, - info: winutil::file::Information, - ) -> Handle { - Handle { - kind: kind, - key: Some(Key { - volume: info.volume_serial_number(), - index: info.file_index(), - }), - } - } - - pub fn stdin() -> io::Result<Handle> { - Handle::from_std_handle(winutil::HandleRef::stdin()) - } - - pub fn stdout() -> io::Result<Handle> { - Handle::from_std_handle(winutil::HandleRef::stdout()) - } - - pub fn stderr() -> io::Result<Handle> { - Handle::from_std_handle(winutil::HandleRef::stderr()) - } - - pub fn as_file(&self) -> &File { - match self.kind { - HandleKind::Owned(ref h) => h.as_file(), - HandleKind::Borrowed(ref h) => h.as_file(), - } - } - - pub fn as_file_mut(&mut self) -> &mut File { - match self.kind { - HandleKind::Owned(ref mut h) => h.as_file_mut(), - HandleKind::Borrowed(ref mut h) => h.as_file_mut(), - } - } -} |
