#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <sys/inotify.h>
namespace asio = boost::asio;
struct test_inotify_asio
{
asio::io_service io_svc;
asio::posix::stream_descriptor stream_desc;
std::string file_path;
int raw_fd;
int watch_fd;
asio::streambuf buf;
test_inotify_asio(const std::string & file_path_)
: stream_desc(io_svc),
file_path(file_path_),
buf(1024)
{
if(0 < (raw_fd = inotify_init()))
{
if(0 > (watch_fd = inotify_add_watch
(raw_fd,
file_path.c_str(),
IN_MODIFY | IN_ACCESS | IN_CREATE | IN_DELETE | IN_OPEN)))
{
throw std::runtime_error("Unable to add watch on: " +
file_path);
}
}
else
{
throw std::runtime_error("Unable to initialize inotify");
}
stream_desc.assign(raw_fd);
start_notify_handler();
};
void start_notify_handler()
{
stream_desc
.async_read_some(buf.prepare(buf.max_size()),
boost::bind
(&test_inotify_asio::notify_handler,
this,
asio::placeholders::error,
asio::placeholders::bytes_transferred));
}
void notify_handler(const boost::system::error_code&,
std::size_t transferred)
{
size_t processed = 0;
while(transferred - processed >= sizeof(inotify_event))
{
const char* cdata = processed + asio::buffer_cast<const char*>(buf.data());
const inotify_event* ievent = reinterpret_cast<const inotify_event*>(cdata);
processed += sizeof(inotify_event) + ievent->len;
if(ievent->len > 0 && ievent->mask & IN_MODIFY)
{
std::cout << "File modified: "
<< file_path
<< "[" << ievent->name << "]\n";
}
else if(ievent->len > 0 && ievent->mask & IN_ACCESS)
{
std::cout << "File accessed: "
<< file_path
<< "[" << ievent->name << "]\n";
}
else if(ievent->len > 0 && ievent->mask & IN_OPEN)
{
std::cout << "File opened: "
<< file_path
<< "[" << ievent->name << "]\n";
}
else if(ievent->len > 0 && ievent->mask & IN_CREATE)
{
std::cout << "File created: "
<< file_path
<< "[" << ievent->name << "]\n";
}
else if(ievent->len > 0 && ievent->mask & IN_DELETE)
{
std::cout << "File deleted: "
<< file_path
<< "[" << ievent->name << "]\n";
}
}
start_notify_handler();
}
void operator()()
{
io_svc.run();
}
~test_inotify_asio()
{
inotify_rm_watch(raw_fd, watch_fd);
close(raw_fd);
}
};
int main()
{
test_inotify_asio tia("/abs/path/to/file");
tia();
}