For accessing files, the kernel does keep an open FD of sorts (better than "dev, inode" pair).
But you can't punt this entirely to the shell - the shell has to look at the kernel's idea of the current directory name at startup; all the in-shell tracking can only be done for subsequent changes.
One major caveat is that the kernel's API stupidly relies on a single-step global record and is limited to one page (usually 4096 bytes), rather than reconstructing it component-by-component. So if you change into a deeply nested folder, `getcwd` falls back to the `open(".."); readdir` loops. Of course if `PWD` is set correctly it can be used, but if it's not canonical you might have to do the nasty version later.
A more subtle caveat is all the possible end cases:
* you reach the current mount namespace's sense of `/`
* you reach the current mount namespace's sense of `//`, if your environment supports such a thing (note that `readdir` likely fails at the last level though!).
* you reach some other sense of `/` (e.g. from an FD kept open across `chdir`, or an FD passed across a Unix socket from a different mount namespace)
* the directory was not found in the readdir loop (a directory moved due to a race condition, or special filesystems that aren't fully enumerable - this includes /proc/ if you use a thread ID directly - this has a different inode than the main PID which it mostly acts like!).
But you can't punt this entirely to the shell - the shell has to look at the kernel's idea of the current directory name at startup; all the in-shell tracking can only be done for subsequent changes.
One major caveat is that the kernel's API stupidly relies on a single-step global record and is limited to one page (usually 4096 bytes), rather than reconstructing it component-by-component. So if you change into a deeply nested folder, `getcwd` falls back to the `open(".."); readdir` loops. Of course if `PWD` is set correctly it can be used, but if it's not canonical you might have to do the nasty version later.
A more subtle caveat is all the possible end cases:
* you reach the current mount namespace's sense of `/`
* you reach the current mount namespace's sense of `//`, if your environment supports such a thing (note that `readdir` likely fails at the last level though!).
* you reach some other sense of `/` (e.g. from an FD kept open across `chdir`, or an FD passed across a Unix socket from a different mount namespace)
* the directory was not found in the readdir loop (a directory moved due to a race condition, or special filesystems that aren't fully enumerable - this includes /proc/ if you use a thread ID directly - this has a different inode than the main PID which it mostly acts like!).