7

For example, in ZFS under FreeBSD and ZoL, there is a magic .zfs dir inside of each zpool mountpoint and you can use zfs set snapdir=visible to make that .zfs dir visible.

What makes me curious is: if that setting is set to "hidden", how is the .zfs dir actually hidden from the output of an ls -a or shell path-auto-completion, while still being accessible otherwise (you can still cd to it or call stat on it)?

I can't really wrap my mind around this fact, because I somehow think if something is there and accessible it's supposed to be listed in ls -a -- even if it's just magic/virtual in nature.

Can anybody explain how this works? Is there a POSIX conforming way to have a directory that is hidden from ls -a while still being accessible? How do you do it?

  • 1
    One good reason to "hide" the .zfs directory from ls (and other user-space utilities that use readdir()) is to see what happens with the .zfs directory visible. Run something like find . -name somefilename with a visible .zfs directory, the find utility will descend into the .zfs directory and search through every single snapshot for that file name, as well as the actual "active" filesystem. – Andrew Henle Dec 23 '16 at 13:57
7

Well, how to do it is easy enough: ls gets its list from a syscall (or, on Linux, libc function) called readdir. Changing into a directory is done with a separate syscall, chdir. stat is also a different syscall, as are most of the other file operations.

In short, "what's in this directory?" and "access this directory" are completely separate requests of the kernel—so they can be programmed to work differently.

So, to make a directory that doesn't appear in ls -a, you just have the kernel omit it from the results of readdir. But it still works with chdir (etc.), because that's a different syscall.

This isn't so different from having a directory where you have +x permission, but not -r: you can access files and directories inside it, cd into it, etc., but ls will fail. I believe other things have used this arrangement too—for example (and this is from fuzzy memory without looking it up) AFS had a sort-of global /afs namespace where you could connect to any AFS server essentially by cd'ing into its name; an ls on /afs wouldn't show all the world's servers, though. I've seen FUSE filesystems do similar (e.g., cd to connect to an anonymous FTP server).

(I'm not sure whether the zfs arrangement strictly complies with POSIX).

  • 1
    On Linux, there's a getdents() system call that winds up calling the VFS's readdir() implementation, so it's trivial for the ZFS implementation to omit the .zfs entry if the snapdir property is set to hidden. See lxr.free-electrons.com/source/fs/readdir.c?v=2.6.35 for source. The POSIX ls specification seems worded such that leaving the directory out isn't in strict compliance with the standard but I suppose one could argue the "directory" is an implementation detail that's optionally exposed as a directory. – Andrew Henle Dec 22 '16 at 23:08
  • This complies with POSIX because the behavior is indistinguishable from having a concurrent process that always deletes the hidden file just before anyone tries to list it (e.g. by calling readdir) and creates it just before anyone tries to access it (e.g. by calling chdir). – Gilles Dec 22 '16 at 23:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.