How does NC determine if a file is a firmlink?

Internals, experiments, tech stuff
Post Reply
JayB
Posts: 187
Joined: Sun Jan 08, 2017 4:38 pm

How does NC determine if a file is a firmlink?

Post by JayB » Mon Mar 22, 2021 10:49 am

The file /usr/share/firmlinks contains all the static firmlinks of macOS.

XNU's /sys/stat.h contains an SF_FIRMLINK flag:

Code: Select all

https://github.com/apple/darwin-xnu/blob/main/bsd/sys/stat.h#L512
#define SF_FIRMLINK 0x00800000 /* file is a firmlink */
Now, let's look at /Applications as an example, which is a firmlink (flag: 0x00800000) and also has the SF_NOUNLINK flag (0x00100000). That would be a combined flag (hexadecimal) of 0x00900000, which we can test bitwise:

Code: Select all

# example: /Applications
# SF_NOUNLINK & SF_FIRMLINK
# 0x00100000 & 0x00800000 = 0x00900000

# positive example: bitwise check for SF_NOUNLINK
fstat_flags="0x00900000" ; fhex="0x00100000" ; result=$((( $(echo "$fstat_flags") & $fhex ))) ; echo "$result"
# result should be "1048576" (non-zero)

# positive example: bitwise check for SF_FIRMLINK
fstat_flags="0x00900000" ; fhex="0x00800000" ; result=$((( $(echo "$fstat_flags") & $fhex ))) ; echo "$result"
# result should be "8388608" (non-zero)

# negative example: bitwise check for UF_HIDDEN (0x00008000)
fstat_flags="0x00900000" ; fhex="0x00008000" ; result=$((( $(echo "$fstat_flags") & $fhex ))) ; echo "$result"
# result should be "0"
That's all fine, but hypothetical. Because in a real-world scenario, when I read the actual flags of the /Applications directory with the stat command…

Code: Select all

printf '0x%x' "$(stat -f %f "/Applications")"
… stat only returns 0x100000, and not 0x900000, i.e. it only registers SF_NOUNLINK, not SF_NOUNLINK plus SF_FIRMLINK.

In Nimble Commander, however, /Applications is correctly represented with "No unlink" and "Firmlink" under Command > File Attributes.

So how does NC do it? Is there another way to get the actual flags in Terminal, or is this an Apple problem specific to the command-line, i.e. certain flags are omitted from (were never included in) the stat output?

Or is this a general macOS problem, i.e. NC actually has to parse /usr/share/firmlinks to check if a certain filepath is a firmlink or not?

User avatar
mike
Posts: 976
Joined: Thu Jul 16, 2015 5:35 am
Location: Exeter, UK

Re: How does NC determine if a file is a firmlink?

Post by mike » Mon Mar 22, 2021 6:34 pm

NC doesn't normally use the info from /usr/share/firmlinks.
I tried to parse it to have a speculative path->device mapping, but gave up at some point, so that code isn't used anymore IIRC.

For the FileAttributes dialog NC doesn't do anything special - the dialog gets data directly from a file listing.
File listing themselves are normally fetched by getattrlistbulk(), which has the same semantics as stat().

JayB
Posts: 187
Joined: Sun Jan 08, 2017 4:38 pm

Re: How does NC determine if a file is a firmlink?

Post by JayB » Mon Mar 22, 2021 8:44 pm

Ah, interesting. Thank you. The man page of getattrlist() says that it's like a "seriously enhanced version of stat(2)". So it seems that Apple simply didn't expand the stat command to include all the latest flags. :(

By the way, would this also work for synthetic firmlinks the user has added to /etc/synthetic.conf or to files in /etc/synthetic.d? (I have a couple of virtual/synthetic firmlinks, and NC doesn't label them in any specific way.)

JayB
Posts: 187
Joined: Sun Jan 08, 2017 4:38 pm

Re: How does NC determine if a file is a firmlink?

Post by JayB » Wed Mar 24, 2021 7:41 am

Strike the synthetic.conf question: the man page says that these are "virtual symbolic links", i.e. no firmlinks at all.

JayB
Posts: 187
Joined: Sun Jan 08, 2017 4:38 pm

Re: How does NC determine if a file is a firmlink?

Post by JayB » Mon Mar 29, 2021 9:50 am

Strike the strike, because there is an extended flag, i.a. for synthetic links. Feature request now here: viewtopic.php?f=6&t=574

Post Reply