Summary
After cd /symlink_folder (where symlink_folder is a symlink to another directory), the prompt and $PWD show the resolved physical path instead of the symlink name the user typed.
Steps to reproduce
$ ln -s /some/deep/path /tmp/mylink
$ cd /tmp/mylink
# prompt shows: /some/deep/path
# expected: /tmp/mylink
Root cause
update_cwd (line ~9978 in bare.asm) unconditionally calls SYS_GETCWD:
update_cwd:
mov rax, SYS_GETCWD
lea rdi, [cwd_buf]
The kernel's getcwd syscall always resolves symlinks and returns the physical path. It is called after every successful chdir, discarding the logical path the user typed.
Expected behavior
POSIX and bash both preserve the logical path through symlinks. Bash maintains $PWD manually — on each cd it normalizes the user-typed path against the current logical $PWD (collapsing .. and . without resolving symlinks) and only calls getcwd for the initial startup value.
Fix sketch
In the cd handler, after SYS_CHDIR succeeds, instead of calling update_cwd:
- If the target path is absolute: normalize it (collapse
//, /./, /../) into cwd_buf directly.
- If relative: append to the current logical
cwd_buf, then normalize.
- Only call
SYS_GETCWD on shell startup (as today) or if cwd_buf is somehow empty.
This matches the POSIX-specified behavior for cd with the logical path option (cd -L, which is the default).
Summary
After
cd /symlink_folder(wheresymlink_folderis a symlink to another directory), the prompt and$PWDshow the resolved physical path instead of the symlink name the user typed.Steps to reproduce
Root cause
update_cwd(line ~9978 inbare.asm) unconditionally callsSYS_GETCWD:The kernel's
getcwdsyscall always resolves symlinks and returns the physical path. It is called after every successfulchdir, discarding the logical path the user typed.Expected behavior
POSIX and bash both preserve the logical path through symlinks. Bash maintains
$PWDmanually — on eachcdit normalizes the user-typed path against the current logical$PWD(collapsing..and.without resolving symlinks) and only callsgetcwdfor the initial startup value.Fix sketch
In the
cdhandler, afterSYS_CHDIRsucceeds, instead of callingupdate_cwd://,/./,/../) intocwd_bufdirectly.cwd_buf, then normalize.SYS_GETCWDon shell startup (as today) or ifcwd_bufis somehow empty.This matches the POSIX-specified behavior for
cdwith the logical path option (cd -L, which is the default).