inotify監聽文件夾的變更

inotify只能監控單層目錄變化,不能監控子目錄中的變化狀況。
若是須要監控子目錄,須要在調用inotify_add_watch(int fd, char *dir, int mask):int創建監控時,遞歸創建子目錄的監控,僞代碼以下
void addwatch(int fd, char *dir, int mask)
{
wd = inotify_add_watch(fd, dir, mask);
向目錄集合加入(wd, dir);
for (dir下全部的子目錄subdir)
addwatch(fd, subdir, mask);
}
這樣就能夠獲得一個目錄集合,其中每個wd對應一個子目錄。
當你調用read獲取信息時,能夠獲得一個下面的結構體
struct inotify_event
{
int wd; /* Watch descriptor. */
uint32_t mask; /* Watch mask. */
uint32_t cookie; /* Cookie to synchronize two events. */
uint32_t len; /* Length (including NULs) of name. */
char name __flexarr; /* Name. */
};
其中,經過event->wd和剛纔記錄的目錄集合能夠知道變更的具體子目錄。
event->name爲具體的文件名稱。
event->name是一個char name[0]形式的樁指針,具體的name佔據的長度能夠由event->len得出

個人監控部分代碼以下:
enum {EVENT_SIZE = sizeof(struct inotify_event)};
enum {BUF_SIZE = (EVENT_SIZE + 16) << 10};
void watch_mon(int fd)
{
int i, length;
void *buf;
struct inotify_event *event;
buf = malloc(BUF_SIZE);

while ((length = read(fd, buf, BUF_SIZE)) >= 0)
{
i = 0;
while (i < length)
{
event = buf + i;
if (event->len)
具體處理函數(event);
i += EVENT_SIZE + event->len;
}
}
close(fd);
exit(1);
}
在你的具體處理函數中,經過wd辨識子目錄,經過name辨識文件

這是利用C++STLmap寫的一個範例,能夠監視當前目錄下(含子目錄)的變化,建立,刪除過程(新創建的目錄不能監視,只能經過監視到建立新目錄的事件後從新初始化監視表)
新版1.1.0,能夠監視建立的子目錄,方法是,當do_action探測到新目錄建立的動做時,調用inotify_add_watch追加新的監視
/*
Copyright (C) 2010-2011 LIU An (SuperHacker@china.com.cn)

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <errno.h>
#include <dirent.h>

#include <map>
#include <string>
using namespace std;

void addwatch(int, char*, int);
static int filter_action(uint32_t mask);
int watch_init(int mask, char *root);
void addwatch(int fd, char *dir, int mask);
static void do_action(int fd, struct inotify_event *event);
void watch_mon(int fd);
static void send_mess(char *name, char *act, int ewd);
void append_dir(int fd, struct inotify_event *event, int mask);

map<int, string> dirset;

enum{MASK = IN_MODIFY | IN_CREATE | IN_DELETE};

int main(int argc, char **argv)
{
int fd;
if (argc != 2)
{
fprintf(stderr, "Usage: %s dir\n", argv[0]);
exit(1);
}

fd = watch_init(MASK, argv[1]);
watch_mon(fd);

return 0;
}

int watch_init(int mask, char *root)
{
int i, fd;

if ((fd = inotify_init()) < 0)
perror("inotify_init");
addwatch(fd, root, mask);
return fd;
}

void addwatch(int fd, char *dir, int mask)
{
int wd;
char subdir[512];
DIR *odir;
struct dirent *dent;

if ((odir = opendir(dir)) == NULL)
{
perror("fail to open root dir");
exit(1);
}
wd = inotify_add_watch(fd, dir, mask);
dirset.insert(make_pair(wd, string(dir)));

errno = 0;
while ((dent = readdir(odir)) != NULL)
{
if (strcmp(dent->d_name, ".") == 0
|| strcmp(dent->d_name, "..") == 0)
continue;
if (dent->d_type == DT_DIR)
{
sprintf(subdir, "%s/%s", dir, dent->d_name);
addwatch(fd, subdir, mask);
}
}

if (errno != 0)
{
perror("fail to read dir");
exit(1);
}

closedir (odir);
}

enum {EVENT_SIZE = sizeof(struct inotify_event)};
enum {BUF_SIZE = (EVENT_SIZE + 16) << 10};

void watch_mon(int fd)
{
int i, length;
void *buf;
struct inotify_event *event;
buf = malloc(BUF_SIZE);

while ((length = read(fd, buf, BUF_SIZE)) >= 0)
{
i = 0;
while (i < length)
{
event = (struct inotify_event*)(buf + i);
if (event->len)
do_action(fd, event);
i += EVENT_SIZE + event->len;
}
}
close(fd);
exit(1);
}

static char action[][10] =
{
"modified",
"accessed",
"created",
"removed"
};

enum{NEWDIR = IN_CREATE | IN_ISDIR};

static void do_action(int fd, struct inotify_event *event)
{
int ia, i;

if ((ia = filter_action(event->mask)) < 0)
return;

if ((event->mask & NEWDIR) == NEWDIR)
append_dir(fd, event, MASK);

send_mess(event->name, action[ia], event->wd);
}

void append_dir(int fd, struct inotify_event *event, int mask)
{
char ndir[512];
int wd;

sprintf(ndir, "%s/%s", dirset.find(event->wd)->second.c_str(),
event->name);
wd = inotify_add_watch(fd, ndir, mask);
dirset.insert(make_pair(wd, string(ndir)));
}

static int filter_action(uint32_t mask)
{
if (mask & IN_MODIFY)
return 0;
if (mask & IN_ACCESS)
return 1;
if (mask & IN_CREATE)
return 2;
if (mask & IN_DELETE)
return 3;
return -1;
}

static void send_mess(char *name, char *act, int ewd)
{
char format[] = "%s was %s.\n";
char file[512];

sprintf(file, "%s/%s", dirset.find(ewd)->second.c_str(), name); printf(format, file, act);}
相關文章
相關標籤/搜索