Hello,

Please find attached the source code. Could anyone explain why the callback
is never invoked when I do change the files?

Thank you,

Roustam
// custom
#include "watcher.h"
// standard
#include <cstring>
// cross-platform
#include <ev++.h>
// Linux
#include <sys/inotify.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>

std::string dir_path;
int file_descriptor, watch_descriptor;
ev::io watcher;
std::list<Event> events;

static void io_callback (ev::io &event_watcher, int revents) {
	events.clear();
	char buffer[4096] __attribute__ ((aligned(__alignof__(struct inotify_event))));
	const struct inotify_event *p_file_event;
	std::size_t event_size = sizeof(struct inotify_event);
	struct stat metadata;
	while (true) {
		ssize_t bytes_count = read(file_descriptor, buffer, sizeof buffer);
		if (bytes_count == -1) {// no new events to process, exit the loop
			if (errno != EAGAIN)
				std::perror("read");
			break;
		}
		// process new events
		for (char *p_event = buffer, *end = buffer + bytes_count; p_event < end; p_event += event_size + p_file_event->len) {
			p_file_event = (const struct inotify_event *) p_event;
			if (!(p_file_event->mask & IN_ISDIR) && p_file_event->len) {// the file is not a directory and has a name
				Event file_event;
				file_event.name = p_file_event->name;
				if (p_file_event->mask & IN_DELETE || p_file_event->mask & IN_MOVED_FROM)// the file was removed
					file_event.status = removed;
				else if(stat((dir_path + '/' + file_event.name).c_str(), &metadata) != -1) {// successfully got file metadata
					file_event.size = (long long) metadata.st_size;
					file_event.modified = ctime(&metadata.st_mtime);
					if (p_file_event->mask & IN_MODIFY || p_file_event->mask & IN_MOVED_TO)// the file was created or modified
						file_event.status = modified;
					else// dismiss the event
						continue;
				}
				else// dismiss the event
					continue;
				events.push_back(file_event);
			}
		}
	}
}

std::list<Event> engage_watcher(const std::string &directory_path) {
	std::list<Event> result;
	if (!dir_path.empty())
		return result;
	struct stat metadata;
	struct dirent *entry = nullptr;// a file
	// open the directory
	DIR *directory = nullptr;
	directory = opendir(directory_path.c_str());
	if (directory != nullptr) {
		dir_path = directory_path;
		// initialize a file descriptor
		file_descriptor = inotify_init1(IN_NONBLOCK);
		if (file_descriptor == -1) {
			std::perror("inotify_init1");
			return result;
		}
		// initialize a watch descriptor
		watch_descriptor = inotify_add_watch(file_descriptor, dir_path.c_str(), IN_MODIFY | IN_MOVED_TO | IN_DELETE | IN_MOVED_FROM);
		if (watch_descriptor == -1) {
			std::fprintf(stderr, "Cannot watch the directory. Error: %s\en", std::strerror(errno));
			close(file_descriptor);
			return result;}
		// iterate through all files in the watched directory
		while ((entry = readdir(directory))) {// get next file from the watched directory
			if (entry->d_type != 4) {// the file is not a directory
				if (stat((dir_path + '/' + entry->d_name).c_str(), &metadata) != -1) {// get file metadata
					Event file_event;
					file_event.name = entry->d_name;
					file_event.size = (long long) metadata.st_size;
					file_event.modified = ctime(&metadata.st_mtime);
					file_event.status = modified;
					result.push_back(file_event);
				}
			}
		}
		// set the callback for the watcher and start watching
		watcher.set <io_callback> ();
		watcher.start(file_descriptor, ev::READ);
		ev::get_default_loop().run(EVRUN_NOWAIT);
	}
	closedir(directory);
	return result;
}

void disengage_watcher() {
	if (dir_path.empty())
		return;
	watcher.stop();
	dir_path.clear();
	inotify_rm_watch(file_descriptor, watch_descriptor);
	close(file_descriptor);
	return;
}
#ifndef WATCHER_H
#define WATCHER_H

// standard
#include <list>
#include <string>

enum FileStatus {modified, removed};

struct Event {
	std::string modified;
	std::string name;
	long long size;
	FileStatus status;
};

std::list<Event> engage_watcher(const std::string &directory_path);
void disengage_watcher();

#endif // WATCHER_H
_______________________________________________
libev mailing list
[email protected]
http://lists.schmorp.de/mailman/listinfo/libev

Reply via email to