You can indeed just re-open the file and re-register a source (deleting the previous one) when DISPATCH_VNODE_DELETE is received. Or you can use a call which was devised for just this kind of scenario, namely dispatch_io_create_with_path() - that will not only watch by path, it will open the file for you and let you read the contents asynchronously.
Since you asked (not sure which technique you asked for, but here's the simplest) here's a stand-alone code sample:
#include <dispatch/dispatch.h>
#include <stdio.h>
int main(int ac, char *av[])
{
int fdes = open("/tmp/pleasewatchthis", O_RDONLY);
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
void (^eventHandler)(void), (^cancelHandler)(void);
unsigned long mask = DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE | DISPATCH_VNODE_EXTEND | DISPATCH_VNODE_ATTRIB | DISPATCH_VNODE_LINK | DISPATCH_VNODE_RENAME | DISPATCH_VNODE_REVOKE;
__block dispatch_source_t source;
eventHandler = ^{
unsigned long l = dispatch_source_get_data(source);
if (l & DISPATCH_VNODE_DELETE) {
printf("watched file deleted! cancelling source
");
dispatch_source_cancel(source);
}
else {
// handle the file has data case
printf("watched file has data
");
}
};
cancelHandler = ^{
int fdes = dispatch_source_get_handle(source);
close(fdes);
// Wait for new file to exist.
while ((fdes = open("/tmp/pleasewatchthis", O_RDONLY)) == -1)
sleep(1);
printf("re-opened target file in cancel handler
");
source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, fdes, mask, queue);
dispatch_source_set_event_handler(source, eventHandler);
dispatch_source_set_cancel_handler(source, cancelHandler);
dispatch_resume(source);
};
source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE,fdes, mask, queue);
dispatch_source_set_event_handler(source, eventHandler);
dispatch_source_set_cancel_handler(source, cancelHandler);
dispatch_resume(source);
dispatch_main();
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…