msys2 / msys2-runtime

Our friendly fork of Cygwin 💖 https://cygwin.org 💖 see the wiki for details
https://github.com/msys2/msys2-runtime/wiki
GNU General Public License v2.0
185 stars 39 forks source link

Investigate why cygdrives don't show up with listdir #195

Open lazka opened 9 months ago

lazka commented 9 months ago

Came up in chat:

zhangxiaoxing commented 9 months ago

This could be annoying at times because in the (somewhat) popular nnn terminal file manager, the user are expected to navigate through whatever they can see. It's quite common that I randomly moved to the msys2 root and got stuck there, because the entire file-system is invisible from there.

lazka commented 9 months ago

Someone in chat mentioned

I seem to remember it was an intentional performance-related change specifically when cygdrives are mounted on the root.

zhangxiaoxing commented 9 months ago

Some further digging revealed this to be a 10+ year old confounding observation that rooted in cygwin/cygdrive. I'm trying to go back to the more conservative mount point of /cygdrive/X but so far editing /etc/fstab and restart msys2 UCRT64 shell doesn't seem to work.

dscho commented 9 months ago

The reason is that the opendir() function (that is called implicitly by ls /) calls into fhander_disk_file::opendir(), not into fhandler_cygdrive::opendir().

Looking at the code, it strikes me as unplanned to have the cygdrive-mount directory be actually read (see fhandler_cygdrive::opendir(): It totally ignores disk contents). Compare that to fhandler_dev::opendir() which very clearly prefers to look at on-disk files, but falls back to faking a directory. The difference gets even more pronounced in the readdir() method, where the fhandler_dev variant first reads the on-disk files, then iterates over the emulated devices and finally the disks/partitions. In contrast, there is nothing at all about real on-disk files in fhandler_cygdrive::readdir().

There's another tell-tale indicating that Cygwin never considered / to be the cygdrive: there are a couple of explicit cygdrive_len > 1 guards, e.g. the one introduced in 3409763ff308ce9a6ee393ba2ac47447ede9fde7.

So I don't think that this is a bug, but it looks like a deliberate design decision on Cygwin's part, and therefore I would expect it to be non-trivial to make the cygdrives show up as part of ls /.

Of course, it would be always possible to imitate fhandler_dev::readdir() in fhandler_disk_file::readdir(), guarded inside an if (mount_table->cygdrive_len == 1 && pc.get_posix() == "/") { ... } block, to specifically append virtual directory entries after the regular on-disk entries have been enumerated. This would happen right here. To hold the necessary state, we would need to extend the __DIR_mounts class (an instance of which is available via d_mounts(dir)).