Search code examples
rustsymlink

How to change working directory in Rust without following symlinks?


I have a symlink like so:

$ mkdir -p /tmp/foo/bar
$ ln -s /tmp/foo/bar /tmp/baz

If I now change the working directory to /tmp/baz with std::env::set_current_dir, I end up at the absolute path /tmp/foo/bar:

use std::env::{current_dir, set_current_dir};

fn main() {
    set_current_dir("/tmp/baz");
    println!("{:?}", current_dir().unwrap()); // prints "/tmp/foo/bar"
}

Is it possible to change the working directory so that current_dir returns the logical path /tmp/baz without resolving the symlink?


Solution

  • std::env::set_current_dir calls the OS dependent implementation.

    In the case of linux, which seems to be the one you're interested into, this calls chdir whose behavior, defined by POSIX, involves solving the symbolic link.

    The working directory can't be, by design, a link. It's a directory.

    As set_current_dir only calls chdir which doesn't keep the trace of the link you gave it, the path you give is lost. If you want to store the path to the symbolic link file, you have to store it yourself in your user code.