Remove Windows verbatim drive in path

`canonicalize` replaces the drive in a path with verbatim syntax,
e.g. `C:\Windows` turns into `\\?\C:\Windows`.

While Win32 apis handle verbatim paths nicely, commonly used Windows
shells like PowerShell and cmd do not, so we remove the prefix
before adding any paths to the database.
This commit is contained in:
Jason Shirk 2020-04-08 21:50:01 -07:00
parent aab37dfab9
commit 0aeba8d09b
2 changed files with 25 additions and 1 deletions

View File

@ -1,5 +1,6 @@
use crate::config; use crate::config;
use crate::dir::{Dir, Epoch, Rank}; use crate::dir::{Dir, Epoch, Rank};
use crate::util;
use anyhow::{anyhow, bail, Context, Result}; use anyhow::{anyhow, bail, Context, Result};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -188,6 +189,7 @@ impl DB {
let path_abs = path let path_abs = path
.as_ref() .as_ref()
.canonicalize() .canonicalize()
.and_then(|path| Ok(util::remove_verbatim_disk_in_path(path)))
.with_context(|| anyhow!("could not access directory: {}", path.as_ref().display()))?; .with_context(|| anyhow!("could not access directory: {}", path.as_ref().display()))?;
match self.data.dirs.iter_mut().find(|dir| dir.path == path_abs) { match self.data.dirs.iter_mut().find(|dir| dir.path == path_abs) {

View File

@ -7,7 +7,7 @@ use anyhow::{anyhow, bail, Context, Result};
use std::cmp::Reverse; use std::cmp::Reverse;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::path::Path; use std::path::{Component, Path, PathBuf, Prefix};
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use std::time::SystemTime; use std::time::SystemTime;
@ -26,6 +26,28 @@ pub fn path_to_bytes<P: AsRef<Path>>(path: &P) -> Result<&[u8]> {
} }
} }
#[cfg(not(windows))]
pub fn remove_verbatim_disk_in_path(path: PathBuf) -> PathBuf {
path
}
#[cfg(windows)]
pub fn remove_verbatim_disk_in_path(path: PathBuf) -> PathBuf {
let mut new_path = PathBuf::new();
for component in path.components() {
if let Component::Prefix(prefix) = component {
if let Prefix::VerbatimDisk(drive) = prefix.kind() {
new_path.push(format!("{}:", drive as char));
continue;
}
}
new_path.push(component);
}
new_path
}
#[cfg(unix)] #[cfg(unix)]
pub fn bytes_to_path(bytes: &[u8]) -> Result<&Path> { pub fn bytes_to_path(bytes: &[u8]) -> Result<&Path> {
use std::ffi::OsStr; use std::ffi::OsStr;