From 0aeba8d09bc8cf9011ae922f843ebe8517668aef Mon Sep 17 00:00:00 2001 From: Jason Shirk Date: Wed, 8 Apr 2020 21:50:01 -0700 Subject: [PATCH] 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. --- src/db.rs | 2 ++ src/util.rs | 24 +++++++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/db.rs b/src/db.rs index df33498..22fd2ff 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,5 +1,6 @@ use crate::config; use crate::dir::{Dir, Epoch, Rank}; +use crate::util; use anyhow::{anyhow, bail, Context, Result}; use serde::{Deserialize, Serialize}; @@ -188,6 +189,7 @@ impl DB { let path_abs = path .as_ref() .canonicalize() + .and_then(|path| Ok(util::remove_verbatim_disk_in_path(path))) .with_context(|| anyhow!("could not access directory: {}", path.as_ref().display()))?; match self.data.dirs.iter_mut().find(|dir| dir.path == path_abs) { diff --git a/src/util.rs b/src/util.rs index 89d7a51..396e80c 100644 --- a/src/util.rs +++ b/src/util.rs @@ -7,7 +7,7 @@ use anyhow::{anyhow, bail, Context, Result}; use std::cmp::Reverse; use std::io::{Read, Write}; -use std::path::Path; +use std::path::{Component, Path, PathBuf, Prefix}; use std::process::{Command, Stdio}; use std::time::SystemTime; @@ -26,6 +26,28 @@ pub fn path_to_bytes>(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)] pub fn bytes_to_path(bytes: &[u8]) -> Result<&Path> { use std::ffi::OsStr;