2008年11月6日 星期四

使用 inotify 監視某資料夾的一舉一動

Standard
在 Linux 下監視某個資料夾的變化,有很多種方法,可以土法煉鋼的定時去掃描、檢查修改時間,也可以去將檔案一一開啟比對,不過往往這些過程,都伴隨著大量且多餘的 IO 存取。對此,使用 inotify 就顯得比較方便且有效率。自從 hal 的出現後,我們已經可以使用 inotify 去攔截某個檔案或資料夾一舉一動的 event,若是整合 GLib ,短短數行即可實作出來。
#include <glib.h>
#include <sys/inotify.h>
#include <sys/types.h>
#include <errno.h>

void inotify_events_io_func(GIOChannel *channel, GIOCondition condition, gpointer data)
{
char buf[1024];
struct inotify_event *event;
gint index = 0;
gint len = 0;
gint fd = g_io_channel_unix_get_fd(channel);

while(((len = read(fd, &buf, sizeof(buf))) < 0) && (errno == EINTR));

while(index<len) {
event = (struct inotify_event*)(buf+index);

/* read events */
switch(event->mask)
{
case IN_MODIFY:
printf("MODIFY\n");
break;
case IN_CREATE
printf("CREATE\n");
break;
case IN_DELETE:
printf("DELETE\n");
break;
}

index += sizeof(struct inotify_event) + event->len;
}
}

int main(int argc, char* argv[])
{
GMainLoop *loop;
GIOChannel *channel;
gint ino_fd = 0;
gint ino_wd = 0;

/* inotify */
ino_fd = inotify_init();
ino_wd = inotify_add_watch(ino_fd, "/usr/share/applications", IN_MODIFY | IN_CREATE | IN_DELETE);
channel = g_io_channel_unix_new(ino_fd);
g_io_add_watch(channel, G_IO_IN, (GIOFunc)inotify_events_io_func, (gpointer)NULL);

loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(loop);
}

該範例將會監聽 /usr/share/applications 資料夾內的檔案更動 event ,並印出來。因為該資料夾是 FreeDesktop.org Spec 中用來記錄桌面 application 資訊的,當安裝或是刪除軟體時,即會收到檔案新增或刪除的 event。