Summary
When calling junction::create() with paths that have the Windows verbatim prefix (\\?\), the function returns Ok(()) but creates a broken junction that cannot be accessed.
Environment
- OS: Windows 10/11
- Rust: stable (1.83)
- Crate version: junction 1.3.0
Reproduction
fn main() {
let tmp = tempfile::tempdir().unwrap();
// Create target directory
let target = tmp.path().join("data").join("dir");
std::fs::create_dir_all(&target).unwrap();
// Create link parent
let link_parent = tmp.path().join("links");
std::fs::create_dir_all(&link_parent).unwrap();
let link = link_parent.join("junc");
// Canonicalize to get verbatim paths (\\?\C:\...)
let target_verbatim = std::fs::canonicalize(&target).unwrap();
let link_parent_verbatim = std::fs::canonicalize(&link_parent).unwrap();
let link_verbatim = link_parent_verbatim.join("junc");
println!("Target: {:?}", target_verbatim);
println!("Link: {:?}", link_verbatim);
// Create junction with verbatim paths
let result = junction::create(&target_verbatim, &link_verbatim);
println!("Create result: {:?}", result);
// Try to access the junction
let meta = std::fs::metadata(&link_verbatim);
println!("Metadata: {:?}", meta);
// Check what the junction target is
let target_read = junction::get_target(&link_verbatim);
println!("Target read: {:?}", target_read);
}
Expected Behavior
Junction is created and accessible:
Create result: Ok(())
Metadata: Ok(...)
Target read: Ok("\\?\C:\Users\...\data\dir")
Actual Behavior
Junction creation appears to succeed but the junction is broken:
Create result: Ok(())
Metadata: Err(Os { code: 123, kind: InvalidFilename, message: "The filename, directory name, or volume label syntax is incorrect." })
Target read: Err(Custom { kind: NotFound, error: "`junction` does not exist" })
Workaround
Strip the \\?\ prefix before passing paths to junction::create():
fn strip_verbatim_prefix(path: &Path) -> Cow<'_, Path> {
let s = path.as_os_str().to_string_lossy();
if let Some(rest) = s.strip_prefix(r"\\?\") {
Cow::Owned(PathBuf::from(rest))
} else {
Cow::Borrowed(path)
}
}
// Use stripped paths
junction::create(
strip_verbatim_prefix(&target_verbatim).as_ref(),
strip_verbatim_prefix(&link_verbatim).as_ref()
)?;
Analysis
The verbatim prefix (\\?\) is commonly produced by std::fs::canonicalize() on Windows. Since junctions are NTFS reparse points and the Windows API should handle verbatim paths, the issue might be in how the path is being stored in the reparse point data structure or how it's being converted for the NTFS API call.
Impact
This affects any code that uses canonicalized paths with the junction crate, which is a common pattern for security-sensitive applications that need to resolve symlinks before creating junctions.
Summary
When calling
junction::create()with paths that have the Windows verbatim prefix (\\?\), the function returnsOk(())but creates a broken junction that cannot be accessed.Environment
Reproduction
Expected Behavior
Junction is created and accessible:
Actual Behavior
Junction creation appears to succeed but the junction is broken:
Workaround
Strip the
\\?\prefix before passing paths tojunction::create():Analysis
The verbatim prefix (
\\?\) is commonly produced bystd::fs::canonicalize()on Windows. Since junctions are NTFS reparse points and the Windows API should handle verbatim paths, the issue might be in how the path is being stored in the reparse point data structure or how it's being converted for the NTFS API call.Impact
This affects any code that uses canonicalized paths with the junction crate, which is a common pattern for security-sensitive applications that need to resolve symlinks before creating junctions.