pierreRIP的专栏

记性是越来越差,很多学过的弄过的东西都会忘记,就从现在开始把着手过的东西稍稍记下来,方便以后看和用吧。

接触inotify是由于这次实习要做一个类似桌面搜索引擎的东西,可能会用到inotify来进行监控,就试着去了解了下,感觉还是不错的。怎么说呢,inotify还是挺容易学习和进行一些简单的操作的,无论是在终端还是应用它的API。基本的东西就不说了,差不多可以搜点别人的资料或者看inotify的首页就能有个不错的理解。简单说下就是三个主要调用。inotify_init()进行文件描述符的初始化,inotify_add_watch()用来添加监察,inotify_rm_watch()用来移出现有监察。然后监察期间所发生的事件可以通过read()函数来获取。

inotify所能监察的事件是比较完整的,但是有个缺点就是它只能监察给定的目录,,而不能对该目录下的子目录有同样的功能。当然我们可以一个个添加一个要监察的目录列表,如果不多的话还是可以的,但如果有很多子目录的话就比较过分了。所以做一个递归还是比较需要的。当然,有fanotify这个东西是自带递归的,但是它所管的事件不是非常完整,当然需求不高的话可以用它。

我在网上找关于inotify递归,但没找着合适的,就只能自己修改下inotify首页给出的列子,加个递归进去。代码写的搓,就给有需要的人来个可以修改的东西吧,也当给自己这两天做的事情做个记录。

#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <sys/inotify.h>#include <unistd.h>#include <poll.h>#include <dirent.h>#include <sys/stat.h>#include <string.h>#include <fcntl.h>#define EXIT_FAILURE 1;#define EXIT_SUCCESS 0;#define NUM_MAX 100int fd;int* wd = NULL;int argc_all;char* argv_all[NUM_MAX];char* SubDir;void GetSubDir(char* dir) {DIR* dp;struct dirent* entry;struct stat statbuf;if ((dp = opendir(dir)) == NULL) {printf("can't open this directory.\n");perror("opendir");exit(1);}chdir(dir);while ((entry = readdir(dp)) != NULL) {char fullname[255];asprintf(&SubDir, "%s/%s", dir, entry->d_name);memset(fullname, 0, sizeof(fullname));lstat(entry->d_name, &statbuf);strncpy(fullname, dir, sizeof(fullname));strncat(fullname, "/", sizeof(fullname));strncat(fullname, entry->d_name, sizeof(fullname));if (entry->d_name[0] == '.')continue;if (S_IFDIR & statbuf.st_mode) {argv_all[argc_all] = SubDir;argc_all++;GetSubDir(fullname);}}chdir("..");closedir(dp);}int init_fd() {// create the file descriptor for accessing inotify APIint fd = inotify_init1(IN_NONBLOCK);if (fd == -1) {perror("inotify_init1");exit(1);}return fd;}int* init_wd(int fd, int argc, char* argv[]) {// create the watch descriptor for root filewd = (int*) calloc(argc, sizeof(int));// allocate memory for watch descriptorsif (wd == NULL) {perror("calloc");exit(1);}//printf("%d\n", argc);for (int i = 1; i < argc; i++) {wd[i] = inotify_add_watch(fd, argv[i], IN_ALL_EVENTS);if (wd[i] == -1) {fprintf(stderr, "Cannot watch '%s'\n", argv[i]);perror("inotify_add_watch");exit(1);}}return wd;}static void Events_Handle(int fd, int* wd, int argc, char* argv[]) {char buf[4096]__attribute__ ((aligned(__alignof__(struct inotify_event))));const struct inotify_event* event;int i;ssize_t len;char* ptr;for (;;) {//read events from inotify file descriptorlen = read(fd, buf, sizeof buf);if (len == -1 && errno != EAGAIN) {perror("read");exit(1);}if (len <= 0)break;for (ptr = buf; ptr < buf + len;//loop over all events in the bufferptr += sizeof(struct inotify_event) + event->len) {event = (const struct inotify_event*) ptr;char name[50];if (event->mask & IN_ISDIR) {//print events typestrncpy(name, event->name, sizeof(name));strncat(name, "/", sizeof(name));printf(" [Directory: ");for (i = 1; i < argc; i++) {if (wd[i] == event->wd) {printf("%s/", argv[i]);break;}}if (event->len)printf("%s] — ", name);elseprintf("] — ");if (event->mask & IN_OPEN)printf("Directory was opened.\n");if (event->mask & IN_CLOSE_NOWRITE)printf("Directory was closed with no writing.\n");if (event->mask & IN_CREATE)printf("Directory was created.\n");if (event->mask & IN_DELETE)printf("Directory was deleted.\n");if (event->mask & IN_DELETE_SELF)printf("Directory was self deleted.\n");if (event->mask & IN_ATTRIB)printf("Metadata was changed.\n");if (event->mask & IN_MOVE_SELF)printf("Directory was self moved.\n");if (event->mask & IN_MOVED_FROM)printf("Old directory name when rename.\n");if (event->mask & IN_MOVED_TO)printf("New directory name when rename.\n");} else {printf(" [File: ");for (i = 1; i < argc; i++) {if (wd[i] == event->wd) {printf("%s/", argv[i]);break;}}if (event->len)printf("%s] — ", event->name);elseprintf("] — ");if (event->mask & IN_OPEN)printf("File was opened.\n");if (event->mask & IN_ACCESS)printf("File was accessed.\n");if (event->mask & IN_CLOSE_WRITE)printf("File was closed with writing.\n");if (event->mask & IN_CLOSE_NOWRITE)printf("File was closed with no writing.\n");if (event->mask & IN_MODIFY)printf("File was modified.\n");if (event->mask & IN_CREATE)printf("File was created.\n");if (event->mask & IN_DELETE)printf("File was deleted.\n");if (event->mask & IN_DELETE_SELF)printf("File was self deleted.\n");if (event->mask & IN_ATTRIB)printf("Metadata was changed.\n");if (event->mask & IN_MOVE_SELF)printf("File was self moved.\n");if (event->mask & IN_MOVED_FROM)printf("Old filename when rename.\n");if (event->mask & IN_MOVED_TO)printf("New filename when rename.\n");}}}}int main(int argc, char* argv[]) {char buf;int poll_num;nfds_t nfds;struct pollfd fds[2];argc_all = argc;for (int i = 0; i < argc_all; i++) {argv_all[i] = argv[i];}//define the Usageif (argc_all < 2) {printf("Usage: %s DIRECTORY [DIRECTORY]\n", argv_all[0]);exit(1);}//initialize file descriptors and watch descriptors of the directory, including the sub-directoriesfor (int i = 1; i < argc; i++) {GetSubDir(argv[i]);}fd = init_fd();wd = init_wd(fd, argc_all, argv_all);//prepare for pollingnfds = 2;fds[0].fd = STDIN_FILENO;fds[0].events = POLLIN;fds[1].fd = fd;fds[1].events = POLLIN;//wait for events and/or terminal inputprintf("———-Listening begins now———-\n");printf("———-Press ENTER to terminate———-\n");printf("\n%s — [Root Directory Watched]\n\n", argv_all[1]);while (1) {poll_num = poll(fds, nfds, -1);if (poll_num == -1) {if (errno == EINTR)continue;perror("poll");exit(1);}if (poll_num > 0) {if (fds[0].revents & POLLIN) {while (read(STDIN_FILENO, &buf, 1) > 0 && buf != '\n')continue;break;}if (fds[1].revents & POLLIN) {Events_Handle(fd, wd, argc_all, argv_all);}}}printf("———-Listing for events stopped———-\n");//close inotify file descriptor and release memoryclose(fd);free(wd);free(SubDir);exit(0);}

一旦有了意志,脚步也会轻松起来。

pierreRIP的专栏

相关文章:

你感兴趣的文章:

标签云: