c - OSX FSEventStreamEventFlags 无法正常工作

标签 c macos core-foundation fsevents

我正在监视文件系统事件的目录。除了一个异常(exception),一切似乎都运行良好。当我第一次创建文件时,它吐出它已创建。然后我可以删除它,它说它已被删除。当我再次创建同一个文件时,我同时获得了一个已创建和已删除的标志。我显然误解了在调用回调时如何设置标志。这里发生了什么?

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

最佳答案

据我所知,您必须寻找 kFSEventStreamEventFlagItemRemovedkFSEventStreamEventFlagItemCreated,然后使用 stat() 或类似的检查文件是否确实被添加或删除。 FSEvents 文档似乎暗示了这一点。

看起来 API 正在对事件位进行“或”运算……所以实际上它是自创建 FSEventsListener 以来所做的所有更改的“或”运算。由于情况似乎如此,另一种选择可能是每次都创建一个新的 FSEventListener(并使用合并计时器选项)。

我做了一些谷歌搜索,但没有找到这个问题的其他示例,甚至没有找到苹果示例代码,但我并没有花太长时间。

我以前使用过 kqueue API:https://gist.github.com/nielsbot/5155671 (这个要点是一个围绕 kqueue 的 obj-c 包装器)

我更改了您的示例代码以显示为每个 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;
}

关于c - OSX FSEventStreamEventFlags 无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18415285/

相关文章:

C - 二维动态数组(双指针) - 共享内存

在 Mac OS X 中进行 iPhone 编程,而不是在 Mac 计算机上运行

ios - 在没有mac的情况下使用phonegap开发ios应用程序

objective-c - [[NSMutableData alloc] initWithLength :] and CFDataCreateMutable()? 之间的区别

c - 使用 cblas_sgemm 执行复杂的矩阵操作以进行乘法

c - 如何使 switch 语句正确循环?

c - 如何在另一个函数中访问这个二维数组?

php - 有没有办法在使用 coda 的 Mac 商店中使用 SVN 进行 Web 开发?

ios - 如何转发声明 CoreFoundation 类型?

iphone - 确定使用 NSString draw/size 方法绘制什么子字符串