summaryrefslogtreecommitdiff
path: root/dmonwrapper.cpp
blob: 6e1b14eab931fdc03467c2c2a8fd767545d91eaf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include "binaryninjaapi.h"
#define DMON_IMPL

#include "dmonwrapper.h"


bool DMonWrapper::DMON_INITIALIZED = false;
std::mutex DMonWrapper::DMON_MUTEX;


DMonWrapper::DMonWrapper()
{
	std::unique_lock<std::mutex> lock(DMON_MUTEX);

	if (!DMON_INITIALIZED)
	{
		dmon_init();
		DMON_INITIALIZED = true;
	}
}


DMonWrapper::~DMonWrapper()
{
	std::unique_lock<std::mutex> lock(DMON_MUTEX);

	if (DMON_INITIALIZED)
	{
		for (const auto& i : m_callbacks)
		{
			dmon_watch_id id;
			id.id = i.first;

			dmon_unwatch(id);
			free(i.second);
		}
		m_callbacks.clear();
	}
}


dmon_watch_id DMonWrapper::Watch(const std::filesystem::path& path, CallbackFunction callback, bool recursive)
{
	std::unique_lock<std::mutex> lock(DMON_MUTEX);

	auto flags = recursive ? DMON_WATCHFLAGS_RECURSIVE : 0;

	CallbackContext* ctxt = new CallbackContext();
	ctxt->callback = callback;

	dmon_watch_id dmonId = dmon_watch(path.string().c_str(), [](dmon_watch_id watch_id, dmon_action action, const char* rootdir, const char* filepath, const char* oldfilepath, void* userData) {
		CallbackContext* ctxt = reinterpret_cast<CallbackContext*>(userData);
		BinaryNinja::ExecuteOnMainThreadAndWait([ctxt, action, rootdir, filepath, oldfilepath](){
			if (ctxt->callback)
				ctxt->callback(action, rootdir, filepath, oldfilepath == NULL ? "" : oldfilepath);
		});
	}, flags, (void*)ctxt);

	if (dmonId.id == 0)
	{
		BinaryNinja::LogError("Failed to watch path %s", path.string().c_str());
		free(ctxt);
		return dmonId;
	}

	m_callbacks[dmonId.id] = ctxt;

	return dmonId;
}


std::vector<dmon_watch_id> DMonWrapper::GetWatchIds()
{
	std::unique_lock<std::mutex> lock(DMON_MUTEX);

	std::vector<dmon_watch_id> out;
	out.reserve(m_callbacks.size());

	for (const auto& i : m_callbacks)
	{
		dmon_watch_id id;
		id.id = i.first;
		out.push_back(id);
	}

	return out;
}


void DMonWrapper::Unwatch(dmon_watch_id watchId)
{
	std::unique_lock<std::mutex> lock(DMON_MUTEX);

	auto itr = m_callbacks.find(watchId.id);
	if (itr != m_callbacks.end())
	{
		dmon_unwatch(watchId);
		free(itr->second);
		m_callbacks.erase(itr);
	}
}