学习之linux inotify递归

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

接触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 100

int 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 API
	int 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 file
	wd = (int*) calloc(argc, sizeof(int));// allocate memory for watch descriptors
	if (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 descriptor
		len = 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 buffer
				ptr += sizeof(struct inotify_event) + event->len) {
			event = (const struct inotify_event*) ptr;
			char name[50];

			if (event->mask & IN_ISDIR) {					//print events type
				strncpy(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);
				else
					printf("] -- ");
				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);
				else
					printf("] -- ");
				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 Usage
	if (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-directories
	for (int i = 1; i < argc; i++) {
		GetSubDir(argv[i]);
	}
	fd = init_fd();
	wd = init_wd(fd, argc_all, argv_all);

	//prepare for polling
	nfds = 2;
	fds[0].fd = STDIN_FILENO;
	fds[0].events = POLLIN;
	fds[1].fd = fd;
	fds[1].events = POLLIN;

	//wait for events and/or terminal input
	printf("----------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 memory
	close(fd);
	free(wd);
	free(SubDir);
	exit(0);
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值