This is such a stupid problem I run into a lot. Both alternatives (doing things with absolute paths vs doing things entirely with relative paths) seem to have a lot of downsides. Overall relative paths seems to be way better, but then you leave yourself open to problems which "rhyme" with the one OP was talking about.
I was citing rearranging the tree is a potential issue with absolute directories, not with relying on CWD - that certainly could have been clearer.
"Also, you're assuming AT_FDCWD won't be -1, which could be reasonable but isn't guaranteed afaik."
Interesting point regarding guarantees. It's not -1 on any existing OS that I can find (it seems to be -100 on Linux and FreeBSD, -3041965 on Solaris, -2 on AIX), and shouldn't be for precisely this reason, but something to bear in mind if you are working on something more obscure that nonetheless has these functions.
Of course, you shouldn't be relying on reasonable behavior from functions passed a bad FD in general. It's just nice to have the additional defense when that does get missed.
It doesn't turn into a mess if you handle it correctly from the start. The way we ususally handle this in large applications is to have one single class like 'ApplicationPaths' which internally figures out all paths needed. No other code uses paths directly, instead always uses paths relative to ApplicationPaths.AppConfigDir/ApplicationPaths.UserConfigDir/ApplicationPaths.ExecutableDir and so on.
What is evil is a program changing its working directory. That's when it becomes an evil global variable, rather than a non-evil global constant.
I was wondering before if it would be interesting to have a filesystem with transactional locking of paths, though I'm sure the performance would take a hit. Would be kind of cool to be able to do filesystem operations without constantly opening yourself up to race conditions and requiring extremely defensive programming.
I agree that treating cwd as a global constant solves most (at least) of the issues, I'm just poking assumptions to see what ideas arise.
In a sense, this is "still a CWD" - but the differences would be 1) you can maintain multiple at the same time, and 2) you could close it.
Ever heard of PATH_MAX and ENAMETOOLONG? You will if you're using absolute paths everywhere. Sigh