Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- "Ninja"

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 1

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/clean_cache.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
contents: read
steps:
- name: Check out code
uses: actions/checkout@v4
uses: actions/checkout@v5

- name: Cleanup
run: |
Expand Down
15 changes: 10 additions & 5 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@ on:
- '.gitignore'
- 'LICENSE'
- 'README*'
branches-ignore:
- 'dependabot/**'

pull_request:
paths-ignore:
- '.clang*'
- '.gitignore'
- 'LICENSE'
- 'README*'

branches-ignore:
- 'dependabot/**'

schedule:
- cron: '0 0 1 * *'
workflow_dispatch:
Expand All @@ -24,20 +29,20 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 1

- uses: ./.github/actions/install-dependencies

- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v4
with:
languages: cpp

- name: Autobuild
uses: github/codeql-action/autobuild@v3
uses: github/codeql-action/autobuild@v4

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v4

6 changes: 5 additions & 1 deletion .github/workflows/cpp_linter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,22 @@ on:
- '.gitignore'
- 'LICENSE'
- 'README*'
branches-ignore:
- 'dependabot/**'
pull_request:
paths-ignore:
- '.clang*'
- '.gitignore'
- 'LICENSE'
- 'README*'
branches-ignore:
- 'dependabot/**'

jobs:
cpp-linter:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 1

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/readme.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v5
# ISO Langusge Codes: https://cloud.google.com/translate/docs/languages
- name: Adding README - English
uses: dephraiim/translate-readme@main
Expand Down
139 changes: 69 additions & 70 deletions MonitorDir/monitordir_mac.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,83 +3,90 @@
#include <CoreServices/CoreServices.h>

#include <iostream>
#include <thread>

std::string eventFlagsToString(FSEventStreamEventFlags eventFlags)
{
std::cout << "FSEventStreamEventFlags: " << std::to_string(eventFlags) << std::endl;

std::string text;
if ((eventFlags & kFSEventStreamEventFlagNone) != 0U) {
return "None: ";
text += "None";
}
if ((eventFlags & kFSEventStreamEventFlagMustScanSubDirs) != 0U) {
return "MustScanSubDirs: ";
text += "MustScanSubDirs ";
}
if ((eventFlags & kFSEventStreamEventFlagUserDropped) != 0U) {
return "UserDropped: ";
text += "UserDropped ";
}
if ((eventFlags & kFSEventStreamEventFlagKernelDropped) != 0U) {
return "KernelDropped: ";
text += "KernelDropped ";
}
if ((eventFlags & kFSEventStreamEventFlagEventIdsWrapped) != 0U) {
return "EventIdsWrapped: ";
text += "EventIdsWrapped ";
}
if ((eventFlags & kFSEventStreamEventFlagHistoryDone) != 0U) {
return "HistoryDone: ";
text += "HistoryDone ";
}
if ((eventFlags & kFSEventStreamEventFlagRootChanged) != 0U) {
return "RootChanged: ";
text += "RootChanged ";
}
if ((eventFlags & kFSEventStreamEventFlagMount) != 0U) {
return "Mount: ";
text += "Mount ";
}
if ((eventFlags & kFSEventStreamEventFlagUnmount) != 0U) {
return "Unmount: ";
text += "Unmount ";
}
if ((eventFlags & kFSEventStreamEventFlagItemCreated) != 0U) {
return "Created: ";
text += "Created ";
}
if ((eventFlags & kFSEventStreamEventFlagItemRemoved) != 0U) {
return "Removed: ";
text += "Removed ";
}
if ((eventFlags & kFSEventStreamEventFlagItemInodeMetaMod) != 0U) {
return "InodeMetaMod: ";
text += "InodeMetaMod ";
}
if ((eventFlags & kFSEventStreamEventFlagItemRenamed) != 0U) {
return "Renamed: ";
text += "Renamed ";
}
if ((eventFlags & kFSEventStreamEventFlagItemModified) != 0U) {
return "Modified: ";
text += "Modified ";
}
if ((eventFlags & kFSEventStreamEventFlagItemFinderInfoMod) != 0U) {
return "FinderInfoMod: ";
text += "FinderInfoMod ";
}
if ((eventFlags & kFSEventStreamEventFlagItemChangeOwner) != 0U) {
return "ChangeOwner: ";
text += "ChangeOwner ";
}
if ((eventFlags & kFSEventStreamEventFlagItemXattrMod) != 0U) {
return "XattrMod: ";
text += "XattrMod ";
}
if ((eventFlags & kFSEventStreamEventFlagItemIsFile) != 0U) {
return "IsFile: ";
text += "IsFile ";
}
if ((eventFlags & kFSEventStreamEventFlagItemIsDir) != 0U) {
return "IsDir: ";
text += "IsDir ";
}
if ((eventFlags & kFSEventStreamEventFlagItemIsSymlink) != 0U) {
return "IsSymlink: ";
text += "IsSymlink ";
}
if ((eventFlags & kFSEventStreamEventFlagOwnEvent) != 0U) {
return "OwnEvent: ";
text += "OwnEvent ";
}
if ((eventFlags & kFSEventStreamEventFlagItemIsHardlink) != 0U) {
return "IsHardlink: ";
text += "IsHardlink ";
}
if ((eventFlags & kFSEventStreamEventFlagItemIsLastHardlink) != 0U) {
return "IsLastHardlink: ";
text += "IsLastHardlink ";
}
if ((eventFlags & kFSEventStreamEventFlagItemCloned) != 0U) {
return "Cloned: ";
text += "Cloned ";
}
if (text.empty()) {
text = "Unknown " + std::to_string(eventFlags) + "";
} else {
text += ": ";
}
return "Unknown " + std::to_string(eventFlags) + ": ";
return text;
}

class MonitorDir::MonitorDirPrivate
Expand All @@ -101,7 +108,7 @@ class MonitorDir::MonitorDirPrivate
// auto *monitorDir = static_cast<MonitorDirPrivate *>(clientCallBackInfo);
char **paths = static_cast<char **>(eventPaths);
if (paths == nullptr) {
std::cerr << "Error: paths is null." << std::endl;
std::cerr << "Errorpaths is null." << std::endl;
return;
}
for (size_t i = 0; i < numEvents; ++i) {
Expand All @@ -113,54 +120,55 @@ class MonitorDir::MonitorDirPrivate
}
}

void monitor()
bool monitor()
{
std::cout << "addWatch: " << dir << std::endl;
CFStringRef pathToWatch = CFStringCreateWithCString(kCFAllocatorDefault,
dir.c_str(),
kCFStringEncodingUTF8);
CFArrayRef pathsToWatch = CFArrayCreate(kCFAllocatorDefault,
reinterpret_cast<const void **>(&pathToWatch),
1,
nullptr);
std::cout << "addWatch" << dir << std::endl;
auto pathToWatch = CFStringCreateWithCString(kCFAllocatorDefault,
dir.c_str(),
kCFStringEncodingUTF8);
auto pathsToWatch = CFArrayCreate(kCFAllocatorDefault,
reinterpret_cast<const void **>(&pathToWatch),
1,
nullptr);
FSEventStreamContext context{0, this, nullptr, nullptr, nullptr};
FSEventStreamRef stream = FSEventStreamCreate(kCFAllocatorDefault,
monitorCallback,
&context,
pathsToWatch,
kFSEventStreamEventIdSinceNow,
3,
kFSEventStreamCreateFlagFileEvents);
runLoop = CFRunLoopGetCurrent();
FSEventStreamScheduleWithRunLoop(stream, runLoop, kCFRunLoopDefaultMode);
stream = FSEventStreamCreate(kCFAllocatorDefault,
monitorCallback,
&context,
pathsToWatch,
kFSEventStreamEventIdSinceNow,
0.,
kFSEventStreamCreateFlagFileEvents);
if (stream == nullptr) {
std::cerr << "Failed to create FSEventStream" << std::endl;
CFRelease(pathsToWatch);
CFRelease(pathToWatch);
return false;
}
auto queue = dispatch_queue_create(nullptr, nullptr);
FSEventStreamSetDispatchQueue(stream, queue);
FSEventStreamStart(stream);
CFRunLoopRun(); // This will block until the stream is stopped.
FSEventStreamStop(stream);
FSEventStreamInvalidate(stream);
FSEventStreamRelease(stream);
CFRelease(pathsToWatch);
CFRelease(pathToWatch);
return true;
}

void stop()
{
if (nullptr == runLoop) {
if (nullptr == stream) {
return;
}
if (CFRunLoopIsWaiting(runLoop) == 0U) {
CFRunLoopWakeUp(runLoop);
}
CFRunLoopStop(runLoop);
FSEventStreamStop(stream);
FSEventStreamInvalidate(stream);
FSEventStreamRelease(stream);
}

void run() { monitor(); }
bool run() { return monitor(); }

MonitorDir *q_ptr;

CFRunLoopRef runLoop = nullptr;
FSEventStreamRef stream = nullptr;

std::filesystem::path dir;
std::thread monitorThread;
};

MonitorDir::MonitorDir(const std::filesystem::path &dir)
Expand All @@ -179,29 +187,20 @@ MonitorDir::~MonitorDir()

bool MonitorDir::start()
{
if (m_isRunning) {
if (m_isRunning.load()) {
std::cerr << "MonitorDir is already running" << std::endl;
return false;
}

m_isRunning.store(true);
d_ptr->monitorThread = std::thread([this] {
d_ptr->run();
m_isRunning.store(false);
});

return true;
m_isRunning.store(d_ptr->run());
return m_isRunning.load();
}

void MonitorDir::stop()
{
if (!m_isRunning) {
if (!m_isRunning.load()) {
std::cerr << "MonitorDir is not running" << std::endl;
return;
}

d_ptr->stop();
if (d_ptr->monitorThread.joinable()) {
d_ptr->monitorThread.join();
}
}
Loading