Pertanyaan OSX FSEventStreamEventFlags tidak berfungsi dengan benar


Saya menonton direktori untuk acara sistem file. Semuanya tampak berfungsi dengan baik dengan satu pengecualian. Ketika saya membuat file pertama kali, ia mengeluarkan bahwa itu dibuat. Lalu saya dapat menghapusnya dan mengatakan itu dihapus. Ketika saya pergi untuk membuat file yang sama lagi, saya mendapatkan bendera yang dibuat dan dihapus pada saat yang bersamaan. Saya jelas salah mengerti bagaimana bendera-bendera ditetapkan ketika callback dipanggil. Apa yang terjadi disini?

//
//  main.c
//  GoFSEvents
//
//  Created by Kyle Cook on 8/22/13.
//  Copyright (c) 2013 Kyle Cook. All rights reserved.
//

#include <CoreServices/CoreServices.h>
#include <stdio.h>
#include <string.h>

void eventCallback(FSEventStreamRef stream, void* callbackInfo, size_t numEvents, void* paths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) {
    char **pathsList = paths;

    for(int i = 0; i<numEvents; i++) {
        uint32 flag = eventFlags[i];

        uint32 created = kFSEventStreamEventFlagItemCreated;
        uint32 removed = kFSEventStreamEventFlagItemRemoved;

        if(flag & removed) {
            printf("Item Removed: %s\n", pathsList[i]);
        }
        else if(flag & created) {
            printf("Item Created: %s\n", pathsList[i]);
        }
    }
}

int main(int argc, const char * argv[])
{
    CFStringRef mypath = CFSTR("/path/to/dir");
    CFArrayRef paths = CFArrayCreate(NULL, (const void **)&mypath, 1, NULL);

    CFRunLoopRef loop = CFRunLoopGetMain();
    FSEventStreamRef stream = FSEventStreamCreate(NULL, (FSEventStreamCallback)eventCallback, NULL, paths, kFSEventStreamEventIdSinceNow, 1.0, kFSEventStreamCreateFlagFileEvents | kFSEventStreamCreateFlagNoDefer);
    FSEventStreamScheduleWithRunLoop(stream, loop, kCFRunLoopDefaultMode);
    FSEventStreamStart(stream);

    CFRunLoopRun();

    FSEventStreamStop(stream);
    FSEventStreamInvalidate(stream);
    FSEventStreamRelease(stream);

    return 0;
}

13
2017-08-24 05:33


asal


Jawaban:


Sejauh yang saya tahu, Anda harus mencari yang baik kFSEventStreamEventFlagItemRemoved atau kFSEventStreamEventFlagItemCreated, lalu gunakan stat() atau serupa untuk memeriksa apakah file itu sebenarnya ditambahkan atau dihapus. Dokumentasi FSEvents tampaknya mengisyaratkan seperti itu.

Sepertinya API adalah or'ing bit peristiwa bersama-sama ... jadi sebenarnya ini adalah OR dari semua perubahan yang dibuat sejak FSEventsListener dibuat. Karena itu tampaknya menjadi kasusnya, opsi lain mungkin untuk membuat FSEventListener baru setiap kali (dan menggunakan opsi timer gabungan).

Saya melakukan beberapa Googling, tetapi tidak menemukan contoh lain dari masalah ini atau bahkan kode sampel apel, tetapi saya tidak menghabiskan terlalu lama untuk itu.

Saya sebelumnya telah menggunakan API kqueue: https://gist.github.com/nielsbot/5155671 (Inti ini adalah pembungkus obyektif di sekitar kqueue)

Saya mengubah kode contoh Anda untuk menampilkan semua tanda yang ditetapkan untuk setiap FSEvent:

#include <CoreServices/CoreServices.h>
#include <stdio.h>
#include <string.h>

static int __count = 0 ;
void eventCallback(FSEventStreamRef stream, void* callbackInfo, size_t numEvents, void* paths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) {
    char **pathsList = paths;

    printf("callback #%u\n", ++__count ) ;
    const char * flags[] = {
        "MustScanSubDirs",
        "UserDropped",
        "KernelDropped",
        "EventIdsWrapped",
        "HistoryDone",
        "RootChanged",
        "Mount",
        "Unmount",
        "ItemCreated",
        "ItemRemoved",
        "ItemInodeMetaMod",
        "ItemRenamed",
        "ItemModified",
        "ItemFinderInfoMod",
        "ItemChangeOwner",
        "ItemXattrMod",
        "ItemIsFile",
        "ItemIsDir",
        "ItemIsSymlink",
        "OwnEvent"
    } ;

    for(int i = 0; i<numEvents; i++)
    {
        printf("%u\n", i ) ;
        printf("\tpath %s\n", pathsList[i]) ;
        printf("\tflags: ") ;
        long bit = 1 ;
        for( int index=0, count = sizeof( flags ) / sizeof( flags[0]); index < count; ++index )
        {
            if ( ( eventFlags[i] & bit ) != 0 )
            {
                printf("%s ", flags[ index ] ) ;
            }
            bit <<= 1 ;
        }
        printf("\n") ;
    }

    FSEventStreamFlushSync( stream ) ;

}

int main(int argc, const char * argv[])
{
    CFStringRef path = CFStringCreateWithCString( kCFAllocatorDefault, argv[1], kCFStringEncodingUTF8 ) ;
    CFArrayRef paths = CFArrayCreate(NULL, (const void **)&path, 1, &kCFTypeArrayCallBacks );
    if ( path ) { CFRelease( path ) ; }

    CFRunLoopRef loop = CFRunLoopGetCurrent() ;
    FSEventStreamRef stream = FSEventStreamCreate(NULL, (FSEventStreamCallback)eventCallback, NULL, paths, kFSEventStreamEventIdSinceNow, 0, kFSEventStreamCreateFlagFileEvents );
    if ( paths ) { CFRelease( paths ) ; }

    FSEventStreamScheduleWithRunLoop(stream, loop, kCFRunLoopDefaultMode);
    FSEventStreamStart(stream);

    CFRunLoopRun() ;

    FSEventStreamStop(stream);
    FSEventStreamInvalidate(stream);
    FSEventStreamRelease(stream);

    return 0;
}

6
2017-12-31 08:57