#path #symlink #parent #directory #extension #safe

real_parent

Symlink-safe path extension for parent directory

4 releases (breaking)

0.4.0 Jun 27, 2024
0.3.0 Jun 25, 2024
0.2.0 May 27, 2024
0.1.0 May 22, 2024

#383 in Filesystem

Download history 14/week @ 2024-09-11 7/week @ 2024-09-18 9/week @ 2024-09-25 6/week @ 2024-10-02

265 downloads per month

MIT/Apache

16KB
177 lines

real_parent

Provides path extension methods including real_parent which are safe in the presence of symlinks.

Noting that Path::parent gives incorrect results in the presence of symlinks, Path::canonicalize has been used extensively to mitigate this. This comes, however, with some ergonomic drawbacks (see below).

The goal of this crate is to replace eager and early calls to Path::canonicalize with late calls to PathExt::real_parent.

In this way, the user's preferred and natural view of their filesystem is preserved, and parent paths are resolved correctly on a just-in-time basis.

The extensive tests are the best documentation of behaviour for various edge cases.

Rationale

The standard library method Path::parent is not safe in the presence of symlinks. For background information and a comprehensive analysis see the Plan 9 paper Getting Dot-Dot Right.

So far the Rust community has leaned extensively on Path::canonicalize to mitigate this. While this approach avoids path breakage, it has the unpleasant result of making all paths absolute, and resolving symlinks into their underlying physical paths.

Considering that symlinks exist in part to provide an abstracted view of the filesystem, eagerly resolving symlinks to their physical paths could be seen as a violation of encapsulation. That is, a user may prefer to deal with their filesystem in terms of their symlinks rather than being exposed to absolute physical paths. There is a further gain in preferring relative paths to absolute, namely independence from absolute location in the filesystem.

Two scenarios illustate this problem.

Nix

Nix, and expecially Nix Home Manager, make heavy use of symlinks into the Nix store, which is where all software and its configuration is installed.

For example:

> ls -l ~/.config/nushell/*.nu | select name type target
╭───┬─────────────────────────────────────┬─────────┬──────────────────────────────────────────────────────────────────────────────────────────╮
│ # │                name                 │  type   │                                          target                                          │
├───┼─────────────────────────────────────┼─────────┼──────────────────────────────────────────────────────────────────────────────────────────┤
│ 0 │ /home/sjg/.config/nushell/config.nu │ symlink │ /nix/store/vjx9vvdq2nqiz0dmqly9la8mqyz2lcnr-home-manager-files/.config/nushell/config.nu │
│ 1 │ /home/sjg/.config/nushell/env.nu    │ symlink │ /nix/store/vjx9vvdq2nqiz0dmqly9la8mqyz2lcnr-home-manager-files/.config/nushell/env.nu    │
│ 2 │ /home/sjg/.config/nushell/plugin.nu │ file    │                                                                                          │
╰───┴─────────────────────────────────────┴─────────┴──────────────────────────────────────────────────────────────────────────────────────────╯

It would be more ergonomic to avoid surfacing these underlying Nix store paths to the user quite so eagerly.

GNU Stow

GNU Stow is a symlink farm manager. It is often used for managing user dotfiles, or /usr/local.

Use of GNU Stow results in extensive symlink farms, with files appearing to exist in well-known directories alongside one another, where in reality they are symlinks to various locations in the filesystem.

Supported Platforms

real_parent runs on all platforms, with the following caveats on Windows.

  • since the tests create symbolic links, to run the tests on Windows you need to run as administrator 🤯

  • symbolic link behaviour on Windows is awkward, so some tests have had to be disabled on that platform

Isolating exactly what is the cause for weird failures with symbolic link edge cases on Windows is beyond both this author's level of Windows platform expertise and, frankly, interest. Pull requests welcome in this area. Note however that the standard library Path::canonicalize may also fail in these edge cases.

Tests

The tests exercise both relative and absolute paths, including UNC paths on Windows, although this is not evident from the test case data.

To see all the paths tested, run the tests with --nocapture, and look for lines containing verified, e.g. in Nushell:

> cargo test -- --test-threads=1 --nocapture | lines | find verified | to text

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

No runtime deps