3

I'm working on a little hobby project to make my own file explorer. nothing fancy, just view the files in the selected folder and optionally add/edit/rename/delete them.

I'd like for the view I present of the directory to update immediately as the contents change regardless of if those changes were made by my program or not. To that end I discovered inotify() which seems to do exactly what I want. setup a watcher on the currently selected directory and then instead of reading in all the contents again, I can simply read in once and then apply inotify events to my cached copy. For the initial read in there are a few options I'm aware of: nftw(), scandir(), and readdir(). I've currently opted for nftw as I read some concerns about race conditions with readdir, where if the file system is changing while the directory is being read it can produce duplicates or omit things. I'm not sure if the other 2 are safe from that, but I saw nftw used in another open source file manager so I'm assuming it is (correct me if I'm wrong and there is a better mechanism for this).

Now the problem. During initialization of my cache, how can I know what events occurred before, during, and after reading in the contents of the directory? Any events occurring before need to be discarded, any events occurring after need to be applied to my newly created local copy, and anything that happened during is a complete mystery to me.

My naive solution is to do the following:

  1. setup inotify watcher on selected directory
  2. read in entire directory
  3. if inotify has any events, repeat step 2
  4. otherwise the cached copy is good and can have future events applied to it.

This would ensure that the contents of the directory are coherent as any changes would have appeared as an inotify event, but I really dislike that fact that my program could be stuck in a loop if the directory has a lot of constant activity going on in it.

Is there a better way to resolve this issue, does linux provide a mechanism for it, for example maybe there is a way to lock a directory so that I can read it in, then attach my watchers and during that time that area of the file system is immutable? Would that even be a good idea if it was possible for a file manager to do? Is there a better directory reading function than nftw? I dislike how you need to use a glibc system for the no depth traversal features.

J. Doe
  • 127
  • 9
  • `nftw()` is a library function that uses `readdir()`. It can't get around the inherent race condition. – Barmar Aug 19 '23 at 17:18
  • 1
    I closed this as duplicate because it seems like exactly the same problem as described [here](https://stackoverflow.com/questions/7157995/how-do-i-avoid-this-race-condition-with-readdir-inotify) and unfortunately the short answer yo your question is that you can't do better. Let me know if you think this duplicate does not apply for whatever reason. – Marco Bonelli Aug 19 '23 at 17:59
  • To add on to the other answer, I would not worry about this problem. The case where the loop does not end is the case where changes keep happening. What do I expect from an explorer when changes keep happening ? Exactly that: constantly update changes in a loop. You just need to make sure to display what you got each loop. Also, keep in mind that you will potentially have incoherent action (ex: deleting something that doesn't exists). But that would have happened anyway without any race condition, for example if you didn't process an update yet. – ElderBug Aug 19 '23 at 18:10
  • @MarcoBonelli looks to be the same fundamental problem. Shame there is no real solution to this – J. Doe Aug 19 '23 at 18:19
  • @ElderBug My main concern with the constant looping is that I wouldn't draw things until my cache is "ready" and it would never be ready if it's still looping. I suppose I could just always issue a draw update after reading in the directory regardless of if there were events after the fact. That way even if I'm doing things less efficiently, my program isn't frozen – J. Doe Aug 19 '23 at 18:19

0 Answers0