Skip to content

Commit e83338b

Browse files
committed
Use try_canonicalize over canonicalize
1 parent 60178cb commit e83338b

File tree

5 files changed

+48
-47
lines changed

5 files changed

+48
-47
lines changed

src/cargo/core/compiler/compile_kind.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use crate::core::Target;
44
use crate::util::errors::CargoResult;
55
use crate::util::interning::InternedString;
6-
use crate::util::{Config, StableHasher};
6+
use crate::util::{try_canonicalize, Config, StableHasher};
77
use anyhow::Context as _;
88
use serde::Serialize;
99
use std::collections::BTreeSet;
@@ -138,8 +138,7 @@ impl CompileTarget {
138138
// If `name` ends in `.json` then it's likely a custom target
139139
// specification. Canonicalize the path to ensure that different builds
140140
// with different paths always produce the same result.
141-
let path = Path::new(name)
142-
.canonicalize()
141+
let path = try_canonicalize(Path::new(name))
143142
.with_context(|| format!("target path {:?} is not a valid file", name))?;
144143

145144
let name = path

src/cargo/core/compiler/fingerprint/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -367,9 +367,9 @@ use serde::{Deserialize, Serialize};
367367

368368
use crate::core::compiler::unit_graph::UnitDep;
369369
use crate::core::Package;
370-
use crate::util;
371370
use crate::util::errors::CargoResult;
372371
use crate::util::interning::InternedString;
372+
use crate::util::{self, try_canonicalize};
373373
use crate::util::{internal, path_args, profile, StableHasher};
374374
use crate::{Config, CARGO_ENV};
375375

@@ -1941,8 +1941,8 @@ pub fn translate_dep_info(
19411941
) -> CargoResult<()> {
19421942
let depinfo = parse_rustc_dep_info(rustc_dep_info)?;
19431943

1944-
let target_root = target_root.canonicalize()?;
1945-
let pkg_root = pkg_root.canonicalize()?;
1944+
let target_root = try_canonicalize(target_root)?;
1945+
let pkg_root = try_canonicalize(pkg_root)?;
19461946
let mut on_disk_info = EncodedDepInfo::default();
19471947
on_disk_info.env = depinfo.env;
19481948

@@ -1985,7 +1985,7 @@ pub fn translate_dep_info(
19851985
// If canonicalization fails, just use the abs path. There is currently
19861986
// a bug where --remap-path-prefix is affecting .d files, causing them
19871987
// to point to non-existent paths.
1988-
let canon_file = abs_file.canonicalize().unwrap_or_else(|_| abs_file.clone());
1988+
let canon_file = try_canonicalize(&abs_file).unwrap_or_else(|_| abs_file.clone());
19891989

19901990
let (ty, path) = if let Ok(stripped) = canon_file.strip_prefix(&target_root) {
19911991
(DepInfoPathType::TargetRootRelative, stripped)

src/cargo/ops/vendor.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::core::{GitReference, Package, Workspace};
44
use crate::ops;
55
use crate::sources::path::PathSource;
66
use crate::sources::CRATES_IO_REGISTRY;
7-
use crate::util::{CargoResult, Config};
7+
use crate::util::{try_canonicalize, CargoResult, Config};
88
use anyhow::{bail, Context as _};
99
use cargo_util::{paths, Sha256};
1010
use serde::Serialize;
@@ -83,7 +83,7 @@ fn sync(
8383
workspaces: &[&Workspace<'_>],
8484
opts: &VendorOptions<'_>,
8585
) -> CargoResult<VendorConfig> {
86-
let canonical_destination = opts.destination.canonicalize();
86+
let canonical_destination = try_canonicalize(opts.destination);
8787
let canonical_destination = canonical_destination.as_deref().unwrap_or(opts.destination);
8888
let dest_dir_already_exists = canonical_destination.exists();
8989

@@ -125,7 +125,7 @@ fn sync(
125125
// Don't delete actual source code!
126126
if pkg.source_id().is_path() {
127127
if let Ok(path) = pkg.source_id().url().to_file_path() {
128-
if let Ok(path) = path.canonicalize() {
128+
if let Ok(path) = try_canonicalize(path) {
129129
to_remove.remove(&path);
130130
}
131131
}

src/cargo/util/config/mod.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,9 @@ use crate::core::{features, CliUnstable, Shell, SourceId, Workspace, WorkspaceRo
7272
use crate::ops::{self, RegistryCredentialConfig};
7373
use crate::util::auth::Secret;
7474
use crate::util::errors::CargoResult;
75-
use crate::util::validate_package_name;
7675
use crate::util::CanonicalUrl;
7776
use crate::util::{internal, toml as cargo_toml};
77+
use crate::util::{try_canonicalize, validate_package_name};
7878
use crate::util::{FileLock, Filesystem, IntoUrl, IntoUrlWithBase, Rustc};
7979
use anyhow::{anyhow, bail, format_err, Context as _};
8080
use cargo_util::paths;
@@ -433,11 +433,11 @@ impl Config {
433433
// commands that use Cargo as a library to inherit (via `cargo <subcommand>`)
434434
// or set (by setting `$CARGO`) a correct path to `cargo` when the current exe
435435
// is not actually cargo (e.g., `cargo-*` binaries, Valgrind, `ld.so`, etc.).
436-
let exe = self
437-
.get_env_os(crate::CARGO_ENV)
438-
.map(PathBuf::from)
439-
.ok_or_else(|| anyhow!("$CARGO not set"))?
440-
.canonicalize()?;
436+
let exe = try_canonicalize(
437+
self.get_env_os(crate::CARGO_ENV)
438+
.map(PathBuf::from)
439+
.ok_or_else(|| anyhow!("$CARGO not set"))?,
440+
)?;
441441
Ok(exe)
442442
};
443443

@@ -446,7 +446,7 @@ impl Config {
446446
// The method varies per operating system and might fail; in particular,
447447
// it depends on `/proc` being mounted on Linux, and some environments
448448
// (like containers or chroots) may not have that available.
449-
let exe = env::current_exe()?.canonicalize()?;
449+
let exe = try_canonicalize(env::current_exe()?)?;
450450
Ok(exe)
451451
}
452452

src/cargo/util/mod.rs

+32-30
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ pub fn try_canonicalize<P: AsRef<Path>>(path: P) -> std::io::Result<PathBuf> {
157157
return Err(Error::new(ErrorKind::NotFound, "the path was not found"));
158158
}
159159

160+
// This code is based on the unstable `std::path::aboslute` and could be replaced with it
161+
// if it's stabilized.
162+
160163
let path = path.as_ref().as_os_str();
161164
let mut path_u16 = Vec::with_capacity(path.len() + 1);
162165
path_u16.extend(path.encode_wide());
@@ -168,39 +171,38 @@ pub fn try_canonicalize<P: AsRef<Path>>(path: P) -> std::io::Result<PathBuf> {
168171
}
169172
path_u16.push(0);
170173

171-
unsafe {
172-
SetLastError(0);
173-
let len = GetFullPathNameW(path_u16.as_ptr(), 0, &mut [] as *mut u16, ptr::null_mut());
174-
if len == 0 {
175-
let error = GetLastError();
176-
if error != 0 {
177-
return Err(Error::from_raw_os_error(error as i32));
174+
loop {
175+
unsafe {
176+
SetLastError(0);
177+
let len =
178+
GetFullPathNameW(path_u16.as_ptr(), 0, &mut [] as *mut u16, ptr::null_mut());
179+
if len == 0 {
180+
let error = GetLastError();
181+
if error != 0 {
182+
return Err(Error::from_raw_os_error(error as i32));
183+
}
178184
}
179-
}
180-
let mut result: Vec<u16> = std::iter::repeat(0).take(len as usize).collect();
181-
182-
let write_len = GetFullPathNameW(
183-
path_u16.as_ptr(),
184-
result.len().try_into().unwrap(),
185-
result.as_mut_ptr().cast::<u16>(),
186-
ptr::null_mut(),
187-
);
188-
if write_len == 0 {
189-
let error = GetLastError();
190-
if error != 0 {
191-
return Err(Error::from_raw_os_error(error as i32));
185+
let mut result = vec![0u16; len as usize];
186+
187+
let write_len = GetFullPathNameW(
188+
path_u16.as_ptr(),
189+
result.len().try_into().unwrap(),
190+
result.as_mut_ptr().cast::<u16>(),
191+
ptr::null_mut(),
192+
);
193+
if write_len == 0 {
194+
let error = GetLastError();
195+
if error != 0 {
196+
return Err(Error::from_raw_os_error(error as i32));
197+
}
198+
}
199+
200+
if write_len <= len {
201+
return Ok(PathBuf::from(OsString::from_wide(
202+
&result[0..(write_len as usize)],
203+
)));
192204
}
193205
}
194-
assert_eq!(
195-
write_len + 1,
196-
len,
197-
"mismatching requested and written lengths for path {:?}",
198-
path
199-
);
200-
201-
Ok(PathBuf::from(OsString::from_wide(
202-
&result[0..(write_len as usize)],
203-
)))
204206
}
205207
})
206208
}

0 commit comments

Comments
 (0)