I'm working on a realtime virus scanner on OSX. The OSX's command line command fs_usage
can be used to determine folder access in the following way (and can only be run as root user):
fs_usage -w -f pathname | grep '/Users/.*/Documents\|/Users/.*/Downloads' | grep mds
Then, just scan for a line containing the phrase:
open
(4 spaces in front, 4 spaces after)
This will emit when a file is downloaded into the Documents or Downloads folder. You can then do a file hash (sha256 is best) on that and use a SQLite database to check whether you've already previously scanned that file or not. If not, then you can scan that file.
Okay, that's interesting, but what's the C++ or Objective C way to determine folder access like that? I mean, surely the fs_usage
command is using some kind of API for that, right?
One clue I have I think is the Apple File System Events API. However, I just don't quite grasp it from the examples given for my particular scenario.
The following code must be in a
main.m
and not amain.mm
or it won't compile. (SEE ADDENDUM BELOW for C++ (main.mm).) The following code runs in a loop, watching new file creations in/Users/mike/Documents
and/Users/mike/Downloads
. (Sorry, it doesn't support wildcards on those paths -- I wish it did!) Press CTRL+C to exit the run loop.Note in the output, if you download a file, you'll see a consistent flag ID of 125184. If a new file is copied into a folder from the same folder, the flag ID is 128256. If a new file is created fresh (like from an editor), the flag ID is 108544. If an existing file is dragged into a folder, the flag ID is 67584. You'll need to keep experimenting with IDs to see what events you want to trap. For instance, if coding a real-time virus scanner, you'd probably want to detect files moved either by command line, drag and drop, cut/paste, or downloaded from the web to a particular folder. Try various scenarios and subfolders, see the IDs you get, and write code that traps those flag IDs.
Addendum
If you need this to work with main.mm and thus C++, you need to add CoreServices.framework library to the build steps. Then, change this line:
...to this line:
Then change this line:
...to this line:
Then change this line:
...to this line: