Обнаружение доступа к папке в Objective C или C++ в OSX (как команда fs_usage)

Я работаю над антивирусным сканером в реальном времени на OSX. Команда командной строки OSX fs_usage может использоваться для определения доступа к папке следующим образом (и может быть запущен только от имени пользователя root):

fs_usage -w -f pathname | grep '/Users/.*/Documents\|/Users/.*/Downloads' | grep mds

Затем просто отсканируйте строку, содержащую фразу:

    open    

(4 пробела впереди, 4 пробела после)

Это будет излучаться при загрузке файла в папку "Документы" или "Загрузки". Затем вы можете сделать хеш файла (лучше всего sha256) и использовать базу данных SQLite, чтобы проверить, сканировали ли вы этот файл ранее или нет. Если нет, то вы можете отсканировать этот файл.

Хорошо, это интересно, но как C++ или Objective C способ определить доступ к папке таким образом? Я имею в виду, конечно, fs_usage Команда использует какой-то API для этого, верно?

Я думаю, что есть одна подсказка - API событий файловой системы Apple. Однако я просто не совсем понял это из примеров, приведенных для моего конкретного сценария.

1 ответ

Решение

Следующий код должен быть в main.m и не main.mm или это не скомпилируется. (СМ. ДОБАВЛЕНИЕ ВНИЗ для C++ (main.mm).) Следующий код выполняется в цикле, наблюдая за созданием новых файлов в /Users/mike/Documents а также /Users/mike/Downloads, (Извините, он не поддерживает символы подстановки на этих путях - я бы хотел, чтобы это было!) Нажмите CTRL+C, чтобы выйти из цикла выполнения.

Обратите внимание, что если вы скачаете файл, вы увидите непротиворечивый идентификатор флага 125184. Если новый файл копируется в папку из той же папки, идентификатор флага будет 128256. Если новый файл создается свежим (как из редактора), идентификатор флага 108544. Если существующий файл перетаскивается в папку, идентификатор флага 67584. Вам нужно будет продолжать экспериментировать с идентификаторами, чтобы увидеть, какие события вы хотите перехватить. Например, если вы кодируете антивирусный сканер в реальном времени, вы, вероятно, захотите обнаружить файлы, перемещенные либо из командной строки, либо перетаскиванием, вырезанием / вставкой или загрузкой из Интернета в определенную папку. Попробуйте различные сценарии и подпапки, посмотрите полученные идентификаторы и напишите код, который перехватывает эти идентификаторы флагов.

#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;
}

добавление

Если вам нужно это для работы с main.mm и, следовательно, с C++, вам нужно добавить библиотеку CoreServices.framework к этапам сборки. Затем измените эту строку:

char **paths = eventPaths;

... к этой строке:

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

Затем измените эту строку:

void *callbackInfo = NULL;

... к этой строке:

FSEventStreamContext *callbackInfo = NULL;

Затем измените эту строку:

CFAbsoluteTime latency = 1.0; // seconds

... к этой строке:

CFTimeInterval latency = 1.0; // seconds
Другие вопросы по тегам