Обнаружение доступа к папке в 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. Однако я просто не совсем понял это из примеров, приведенных для моего конкретного сценария.

0

Решение

Следующий код должен быть в 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
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]