Skip to content

Don't follow symlinks in append_dir_all() if follow_symlinks(false)#417

Open
nabijaczleweli wants to merge 2 commits into
composefs:mainfrom
nabijaczleweli:main
Open

Don't follow symlinks in append_dir_all() if follow_symlinks(false)#417
nabijaczleweli wants to merge 2 commits into
composefs:mainfrom
nabijaczleweli:main

Conversation

@nabijaczleweli
Copy link
Copy Markdown

Before (append_dir_all("file")):

called `Result::unwrap()` on an `Err` value: Os { code: 20, kind: NotADirectory, message: "Not a directory" }
called `Result::unwrap()` on an `Err` value: Os { code: 267, kind: NotADirectory, message: "The directory name is invalid." }

after (append_dir_all("file") or append_dir_all("symlink"):

called `Result::unwrap()` on an `Err` value: Custom { kind: NotADirectory, error: "append_dir_all() argument not a directory" }

Repro with

fn main() {
    let mut tar = tar::Builder::new(std::io::stdout().lock());
    tar.follow_symlinks(false);
    tar.append_dir_all("", std::env::args_os().nth(1).unwrap()) .unwrap();
    tar.finish().unwrap();
}

before:

$ ls -lnd src symlink Cargo.toml
-rw-r--r-- 1 1000 100 118 10-08 18:31 Cargo.toml
drwxr-xr-x 2 1000 100  60 10-08 17:57 src
lrwxrwxrwx 1 1000 100   3 10-08 18:30 symlink -> src
$ cargo run -- Cargo.toml | tar -tv
called `Result::unwrap()` on an `Err` value: Os { code: 20, kind: NotADirectory, message: "Not a directory" }
$ cargo run -- src | tar -tv
-rw-r--r-- 1000/100        211 2025-10-08 18:29 main.rs
$ cargo run -- symlink | tar -tv
-rw-r--r-- 1000/100        211 2025-10-08 18:29 main.rs

after:

$ cargo run -- Cargo.toml | tar -tv
called `Result::unwrap()` on an `Err` value: Custom { kind: NotADirectory, error: "append_dir_all() argument not a directory" }
$ cargo run -- src | tar -tv
-rw-r--r-- 1000/100        211 2025-10-08 18:29 main.rs
$ cargo run -- symlink | tar -tv
called `Result::unwrap()` on an `Err` value: Custom { kind: NotADirectory, error: "append_dir_all() argument not a directory" }

This also achieves parity with tar(1) which follow_symlinks() touts

Before (append_dir_all("file")):
  called `Result::unwrap()` on an `Err` value: Os { code: 20, kind: NotADirectory, message: "Not a directory" }
  called `Result::unwrap()` on an `Err` value: Os { code: 267, kind: NotADirectory, message: "The directory name is invalid." }
after (append_dir_all("file") or append_dir_all("symlink"):
  called `Result::unwrap()` on an `Err` value: Custom { kind: NotADirectory, error: "append_dir_all() argument not a directory" }

Repro with
  fn main() {
      let mut tar = tar::Builder::new(std::io::stdout().lock());
      tar.follow_symlinks(false);
      tar.append_dir_all("", std::env::args_os().nth(1).unwrap()) .unwrap();
      tar.finish().unwrap();
  }
before:
  $ ls -lnd src symlink Cargo.toml
  -rw-r--r-- 1 1000 100 118 10-08 18:31 Cargo.toml
  drwxr-xr-x 2 1000 100  60 10-08 17:57 src
  lrwxrwxrwx 1 1000 100   3 10-08 18:30 symlink -> src
  $ cargo run -- Cargo.toml | tar -tv
  called `Result::unwrap()` on an `Err` value: Os { code: 20, kind: NotADirectory, message: "Not a directory" }
  $ cargo run -- src | tar -tv
  -rw-r--r-- 1000/100        211 2025-10-08 18:29 main.rs
  $ cargo run -- symlink | tar -tv
  -rw-r--r-- 1000/100        211 2025-10-08 18:29 main.rs
after:
  $ cargo run -- Cargo.toml | tar -tv
  called `Result::unwrap()` on an `Err` value: Custom { kind: NotADirectory, error: "append_dir_all() argument not a directory" }
  $ cargo run -- src | tar -tv
  -rw-r--r-- 1000/100        211 2025-10-08 18:29 main.rs
  $ cargo run -- symlink | tar -tv
  called `Result::unwrap()` on an `Err` value: Custom { kind: NotADirectory, error: "append_dir_all() argument not a directory" }

This also achieves parity with tar(1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant