Я работаю над антивирусным сканером в реальном времени на 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. Однако я просто не совсем понял это из примеров, приведенных для моего конкретного сценария.
Следующий код должен быть в 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
Других решений пока нет …