How to Make My Program Watch For File Modification in C++

How do I make my program watch for file modification in C++?

There are several ways to do this depending on the platform. I would choose from the following choices:

Cross Platform

Trolltech's Qt has an object called QFileSystemWatcher which allows you to monitor files and directories. I'm sure there are other cross platform frameworks that give you this sort of capability too, but this one works fairly well in my experience.

Windows (Win32)

There is a Win32 api called FindFirstChangeNotification which does the job. There is a nice article which a small wrapper class for the api called How to get a notification if change occurs in a specified directory which will get you started.

Windows (.NET Framework)

If you are ok using C++/CLI with the .NET Framework then
System.IO.FileSystemWatcher is your class of choice. Microsoft has a nice article on
how to monitor file system changes using this class.

OS X

The FSEvents API is new for OS X 10.5 and very full-featured.

Linux

Use inotify as Alex mentioned in his answer.

How do I Monitor Text File Changes with C++? Difficulty: No .NET

You can monitor a directory with FindFirstChangeNotification works on any windows.

It's efficent if you know where the file is - otherwise you can use the virtual driver/Filemon described below to check for changes anywhere on the system.

Example code here

Notification when a file changes?

That would be System.IO.FileSystemWatcher.

monitoring file changes c++ linux

When you use inotify, you do not require to poll for all files to check if there are changes. You get a callback system that notifies you when a watched file or directory got changed.

The kernel/filesystem already has this information, so the resource/CPU usage is not just moved to another application, it is actually reduced.

Monitor file system activity with inotify provides more details why to use inotify, shows its basic usage and helps you set it up.

How to stop the repetition of inotify result?

Some remarks:

  • You should not "break" as you go out of the inside "while" loop and call read() again
  • The IN_MODIFY event does not fill the event->name field (i.e. event->len = 0)
  • The number of IN_MODIFY events depends on how you modify the files ("echo xxx >> file" = write only = 1 IN_MODIFY; "echo xxx > file" = truncate + write = 2 IN_MODIFY)

Here is a proposition for your program (with additional prints):

#include <stdio.h>
#include <sys/inotify.h>
#include <unistd.h>
#include <stdlib.h>

#define EVENT_BUF_LEN 4096
#define EVENT_SIZE sizeof(struct inotify_event)

typedef struct{
int length, fd, wd1, wd2;
char buffer[EVENT_BUF_LEN] __attribute__ ((aligned(__alignof__(struct inotify_event))));
} notification;

notification inotify;

int getNotified(char *pathname1, char *pathname2){

inotify.fd = inotify_init();
inotify.wd1 = inotify_add_watch(inotify.fd, pathname1, IN_MODIFY);
printf("wd1 = %d\n", inotify.wd1);
inotify.wd2 = inotify_add_watch(inotify.fd, pathname2, IN_MODIFY);
printf("wd2 = %d\n", inotify.wd2);

while(1){
inotify.length = read(inotify.fd, inotify.buffer, EVENT_BUF_LEN);
int i = 0;
printf("read() = %d\n", inotify.length);
while(i < inotify.length){
struct inotify_event *event = (struct inotify_event *)&inotify.buffer[i];
printf("event->len = %u\n", event->len);
if(event->mask & IN_MODIFY){
if(event->wd == inotify.wd1){
printf("Pathname1 is modified\n");
} else if (event->wd == inotify.wd2){
printf("Pathname2 is modified\n");
}
}
i += (EVENT_SIZE + event->len);
printf("i=%d\n", i);
}
}
inotify_rm_watch(inotify.fd, inotify.wd1);
inotify_rm_watch(inotify.fd, inotify.wd2);

close(inotify.fd);
exit(0);
}



int main(void)
{
getNotified("/tmp/foo", "/tmp/bar");

return 0;

} // main

Here is an example of execution:

$ gcc notif.c -o notif
$ > /tmp/foo
$ > /tmp/bar
$ ./notif
wd1 = 1
wd2 = 2

====== Upon "> /tmp/foo": 1 event (truncate operation)
read() = 16
event->len = 0
Pathname1 is modified
i=16

====== Upon "echo qwerty > /tmp/foo": 2 events (write operation, one event for truncate operation and one for the write of "qwerty" at the beginning of the file)
read() = 16
event->len = 0
Pathname1 is modified
i=16
read() = 16
event->len = 0
Pathname1 is modified
i=16

====== Upon "echo qwerty >> /tmp/foo": 1 event (write of "qwerty" at the end of the file)
read() = 16
event->len = 0
Pathname1 is modified
i=16

Read file changes since the last check without running program constantly in C#

Have a look at the USN Journal for NTFS.

It basically logs all changes to files on an NTFS disk.

Here are some links which might prove useful:

  1. Creating, Modifying, and Deleting a Change Journal
  2. Fsutil usn
  3. File Path from USN Journal


Related Topics



Leave a reply



Submit