in reply to Getting the shell's version of working directory, without PWD's help

On Linux, the getcwd system call returns /home/foo/dir1 in your scenario.

#include <unistd.h> #include <stdio.h> #include <limits.h> int main() { char cwd[PATH_MAX]; if (getcwd(cwd, sizeof(cwd)) == NULL) { perror("getcwd"); return 1; } printf("Current working dir: %s\n", cwd); return 0; }
[~/sym1]$ gcc -Wall -Wextra -pedantic a.c -o a && ./a Current working dir: /home/ikegami/dir1

It's not that bash sets the child's CWD differently than its own; /proc shows that bash's CWD is also resolved.

[~/sym1]$ readlink /proc/$$/cwd /home/ikegami/dir1

In fact, the system call to get the CWD returns the resolved link even if you explicitly set the CWD to the link.

#include <unistd.h> #include <stdio.h> #include <limits.h> int main() { if (chdir("/home/ikegami/sym1")) { perror("chdir"); return 1; } char cwd[PATH_MAX]; if (getcwd(cwd, sizeof(cwd)) == NULL) { perror("getcwd"); return 1; } printf("Current working dir: %s\n", cwd); return 0; }
[~/sym1]$ gcc -Wall -Wextra -pedantic a.c -o a && ./a Current working dir: /home/ikegami/dir1

What this means is that in no way is the process's CWD /home/ikegami/sym1 as you think. So short of trusting $ENV{PWD} to be accurate, it's simply impossible to get /home/ikegami/sym1 from the system since that's not the process's CWD.

use 5.010; use Path::Tiny qw( path ); say path($0)->absolute($ENV{PWD});
[~/sym1]$ perl a.pl /home/ikegami/sym1/a.pl

Do note that this is entirely insecure.

A setuid script that relies on unresolved links in $0 is insecure.
A setuid script that relies on $ENV{PWD} is insecure.

Seeking work! You can reach me at ikegami@adaelis.com

Replies are listed 'Best First'.
Re^2: Getting the absolute path of a script, without PWD
by perlancar (Hermit) on Jul 16, 2021 at 00:56 UTC
    Thanks ikegami. Agreed. The working directory is a location chosen by the user. Due to symlinks one might reach the same location through different paths. And this state is in bash, there's no way of knowing this state unless bash exposes it.

      It does. That's what $ENV{PWD} is. But to use that relies on the parent being process being bash, and it wouldn't be safe for a setuid script to use that.

      Seeking work! You can reach me at ikegami@adaelis.com