8

The inotify_event struct looks like this :

struct inotify_event {
int      wd;       /* Watch descriptor */
uint32_t mask;     /* Mask of events */
uint32_t cookie;   /* Unique cookie associating related
                      events (for rename(2)) */
uint32_t len;      /* Size of name field */
char     name[];   /* Optional null-terminated name */

};

The name part stores only the file name(not the path to the file). How do we get the fully qualified path from the inotify_event struct or do I have to wrap my own struct around it ?

Edit: I wait for the events for around 2s and then process it on one go.I maintain a queue of events. My question is whether I can get the complete path to my file from the inotify_event struct only ?

The number of events per second is large.

bsd
  • 2,707
  • 1
  • 17
  • 24

5 Answers5

5

There are two options:

  1. You're watching a file. You have passed its name to inotify_add_watch, and got a watch descriptor. If you get an event, you can figure out the file by the watch descriptor.

  2. You're watching a directory. Again, you have passed the directory name to inotify_add_watch, and can find which name it was, based on the watch ID. Now inotify_event.name contains the file name. Concatenate the two and you're done.

ugoren
  • 16,023
  • 3
  • 35
  • 65
  • What do you mean by : "If you get an event, you can figure out the file by the watch descriptor." I add all my events to a queue and after around 2s, process it in one shot. – bsd Feb 16 '12 at 14:49
  • @FF Then you should add a hint about the path being monitored. – glglgl Feb 16 '12 at 14:51
  • Each time you add an event, you have a name (which you just passed to `inotify_add_watch` and a descriptor (which you got as a return value). You need to keep this pair in some data structure. Later, when you have a watch descriptor, look there and find the associated name. – ugoren Feb 16 '12 at 14:52
  • Ok , so a pair needs to be maintained. But possibly my program may run for a long time and the file may be moved from one directory to another, modified, deleted etc. is it guaranteed that the wd i get will point to the same file ? – bsd Feb 16 '12 at 14:55
  • No, if a file/directory is renamed/moved you have to use the inotify_event cookie, which is there for exactly this purpose and guaranteed not to change. And you need to monitor for IN_MOVED_* events. – Peter Krnjevic Jul 17 '13 at 01:09
2

I think you need to keep track of each of the watch descriptors as you add them in some structure (all with the full path when you add it). Then, when you receive an event, look up the full path in that structure by using the wd in the event.

wd identifies the watch for which this event occurs. It is one of the watch descriptors returned by a previous call to inotify_add_watch(2).

http://www.kernel.org/doc/man-pages/online/pages/man7/inotify.7.html

Hope that helps...

Homer6
  • 15,034
  • 11
  • 61
  • 81
1

Associate (with a struct) the resulted watch descriptors with the path you add to be watched. Thus you'll created a list of watches. When you get an event it contains the watch descriptor, thus, you'll find the path associated with this watch descriptor from the list of watches. Concatenate the name you get from the event struct with the path you get from the list of watches. Also when you add a path to watch, at this time you'll also add recursively all the sub-paths in the same way you added the parent path.

0

This is ok as far as it goes, but it is not the whole answer.

If you have a directory structure and you are watching file & dir events and it looks like this: /root/dir1 & /root/dir2, then you will not have correct resolution of where a file or dir was created in dir1 or dir2, even after you add them to the watch list.

Inotify returns the name of the item and does not tell you which dir it was in.

octopusgrabbus
  • 10,555
  • 15
  • 68
  • 131
EJC
  • 1
0

The inotify system, uses contiguous numbers as watch descriptors, let's say you want to watch 3 directories, the ../A , the ../B and the ../C , if lets say, I create a file inside ../A , then the watch descriptor return from read() will be 1., if i create a file inside ../C , the watch descriptor will be 3 and so on. So, the association is pretty easy, you can create an array with the paths, and apply inotify_add_watch() to each of them, then, if a event has the watch descriptor x, just piece together the pathsArray[x-1] with the event->name and you have the path :)

std::string getPathFromEvent(struct inotify_event *ptr){
    std::stringstream builder ;
    builder<<directories->DetectedDirectories.operator[](ptr->wd-1).string();
    builder<<ptr->name;
    return builder.str();
}