FTS and firmlinks

chdir (2) with relative paths that involve firmlink black magic behave awkwardly. Consider the following sample code:

#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>


int main(int argc, const char * argv[]) {
    chdir("/System/Volumes/Data/usr/libexec");
    assert(strcmp(getwd(NULL), "/System/Volumes/Data/usr/libexec") == 0);

    chdir("cups");
    assert(strcmp(getwd(NULL), "/System/Volumes/Data/usr/libexec/cups") == 0);

    return 0;
}

The problem is that the second chdir will jump to "/usr/libexec/cups".

I have reported this issue via the feedback assistant (FB11432545) but it got closed as "Works as currently designed" without much explanation.

Especially if you take into account that FTS (3) and tools like ls (1) and find (1) are broken:

$ find /System/Volumes/Data/usr/share | grep '^/System/Volumes/Data/usr/share/' | wc -l
     179

$ find /System/Volumes/Data/usr | grep /System/Volumes/Data/usr/share/ | wc -l
   14956

Yes, there are awkward issues with links, but (a) there is no solution that does what you hope for in every case, and (b) making any change will break some existing code.

In code like your first sample, you cannot assume anything about what getwd() returns. In paranoid code, e.g. anything with security implications, you should be even more cautious because you should assume that someone else has moved a link while you weren't looking.

FTS and firmlinks
 
 
Q