soft-canonicalize
A pure Rust library for path canonicalization that works with non-existing paths.
Unlike std::fs::canonicalize(), this library can resolve and normalize paths even when some or all of the path components don't exist on the filesystem. This is particularly useful for security validation, path preprocessing, and working with paths before creating files.
Features
- 🚀 Works with non-existing paths: Canonicalizes paths even when they don't exist
- 🌍 Cross-platform: Supports Windows, macOS, and Linux
- ⚡ Zero dependencies: No external dependencies beyond std
- 🔒 Security focused: Proper handling of
..components and symlinks - 🧮 Pure algorithm: No filesystem modification during canonicalization
- 📏 Zero-cost abstractions: Minimal performance overhead
Quick Start
Add this to your Cargo.toml:
[]
= "0.0.1"
Examples
Basic Usage
use soft_canonicalize;
use Path;
Directory Traversal Handling
use soft_canonicalize;
use Path;
Security Validation
use soft_canonicalize;
use ;
Algorithm
The soft canonicalization algorithm works in the following steps:
- Absolute Path Conversion: Convert relative paths to absolute paths using the current working directory
- Logical Processing: Process
..components mathematically without filesystem access to resolve directory traversals - Existing Prefix Discovery: Find the longest existing ancestor directory by walking up the path
- Canonicalization: Use
std::fs::canonicalizeon the existing portion to resolve symlinks and normalize - Reconstruction: Append the non-existing components to the canonicalized base
This approach provides the security benefits of full canonicalization while supporting paths that don't exist yet.
Security Considerations
This library is designed with security in mind:
- Directory Traversal Prevention:
..components are resolved logically before any filesystem access - Symlink Resolution: Existing symlinks are properly resolved using standard canonicalization
- No Side Effects: No temporary files or directories are created during the canonicalization process
- Path Injection Protection: Proper handling of various path formats and edge cases
Performance
- Time Complexity: O(n) where n is the number of path components
- Space Complexity: O(n) for component storage during processing
- Filesystem Access: Minimal - only to find existing ancestors and canonicalize them
- Memory Usage: Very low overhead, mostly stack-allocated
Cross-Platform Support
This library works correctly on:
- Windows: Handles drive letters (C:), UNC paths (\\server\share), and case normalization
- Unix-like systems: Handles absolute paths starting with
/and proper symlink resolution - All platforms: Correct handling of path separators (
/vs\\) and component normalization
Comparison with Alternatives
| Feature | soft_canonicalize |
std::fs::canonicalize |
dunce::canonicalize |
|---|---|---|---|
| Works with non-existing paths | ✅ | ❌ | ❌ |
| Resolves symlinks | ✅ | ✅ | ✅ |
Handles .. components |
✅ | ✅ | ✅ |
| Cross-platform | ✅ | ✅ | ✅ |
| Zero dependencies | ✅ | ✅ | ❌ |
| No filesystem modification | ✅ | ✅ | ✅ |
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
License
This project is licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Changelog
See CHANGELOG.md for a detailed history of changes.