Detect Folder Access in Objective C or C++ on OSX (Like fs_usage command)

前端 未结 1 1853
清酒与你
清酒与你 2021-01-28 15:11

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

相关标签:
1条回答
  • 2021-01-28 15:55

    The following code must be in a main.m and not a main.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.

    #import <Foundation/Foundation.h>
    
    void detectNewFile (
        ConstFSEventStreamRef streamRef,
        void *clientCallBackInfo,
        size_t numEvents,
        void *eventPaths,
        const FSEventStreamEventFlags eventFlags[],
        const FSEventStreamEventId eventIds[])
    {
        int i;
        char **paths = eventPaths;
    
        printf("GOT AN EVENT!!!!\n");
        for (i=0; i<numEvents; i++) {
            printf("Change %llu in %s, flags %u\n", eventIds[i], paths[i], (unsigned int)eventFlags[i]);
        }
    }
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
    
            short nPathCount = 2;
            CFStringRef mypath[nPathCount];
            mypath[0] = CFSTR("/Users/mike/Documents");
            mypath[1] = CFSTR("/Users/mike/Downloads");
            CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void **)&mypath, nPathCount, NULL);
            void *callbackInfo = NULL;
            CFAbsoluteTime latency = 1.0; // seconds
    
            FSEventStreamRef hStream = FSEventStreamCreate(NULL,
                &detectNewFile,
                callbackInfo,
                pathsToWatch,
                kFSEventStreamEventIdSinceNow,
                latency,
                kFSEventStreamCreateFlagFileEvents
            );
    
            FSEventStreamScheduleWithRunLoop(hStream, CFRunLoopGetCurrent(),         kCFRunLoopDefaultMode);
            FSEventStreamStart(hStream);
            printf("Waiting on new file creations...\n");
            CFRunLoopRun(); // runs in an endless loop, only letting the callback function run
    
        } // end autorelease pool
        return 0;
    }
    

    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:

    char **paths = eventPaths;
    

    ...to this line:

    char **paths = (char **)eventPaths;
    

    Then change this line:

    void *callbackInfo = NULL;
    

    ...to this line:

    FSEventStreamContext *callbackInfo = NULL;
    

    Then change this line:

    CFAbsoluteTime latency = 1.0; // seconds
    

    ...to this line:

    CFTimeInterval latency = 1.0; // seconds
    
    0 讨论(0)
提交回复
热议问题