如何使用 Kqueue 检测文件何时被发送到垃圾箱?

How can I detect when a file is sent to trash using Kqueue?

我在 mac os x 上使用 Kqueues,我正在尝试监视一个文件夹 所以我使用了 EVFILT_VNODE 过滤器,我想在文件被删除时得到通知,我尝试了 NOTE_DELETE 但它只检测文件何时通过 unlink() system call 被删除,而不是当我移动文件到回收站。

问题是如何检测文件何时被发送到回收站?

没有简单的方法可以做到这一点。 kqueue() 可以在文件被移动(a.k.a. 重命名)时通知您,但它不会将垃圾视为任何类型的特殊目的地或对继续存在有任何特殊意义的文件。也就是说,就 BSD 层而言,将文件移动到回收站就像将它移动到任何其他目录一样。

因此,您将监视 NOTE_RENAME 以查明文件何时为 moved/renamed。然后,您可以使用 fcntl(fd, F_GETPATH, buffer) 找出新路径。请注意,对于硬链接文件,这可能会给出其他链接之一的路径,而不是用户认为的项目路径。不过这种情况应该很少见。

然后您必须查看新路径是否在回收站内。那也复杂。

如果需要 OS X 10.10 或更高版本,则可以使用 [[NSFileManager defaultManager] getRelationship:&relationship ofDirectory:NSTrashDirectory inDomain:0 toItemAtURL:[NSURL fileURLWithPath:pathFromFcntl] error:NULL]。如果该方法 returns 为真并将 relationship 设置为 NSURLRelationshipOther 以外的任何值,则文件已移至垃圾箱。

如果您需要支持 10.9 及更早版本,则必须手动执行此操作:

垃圾目录不止一个。每个卷上的每个用户都有一个不同的目录。要查找特定文件将使用的垃圾目录,请调用 [[NSFileManager defaultManager] URLForDirectory:NSTrashDirectory inDomain:NSUserDomainMask appropriateForURL:[NSURL fileURLWithPath:pathFromFcntl] create:NO error:NULL].

然后您必须确定新路径是否在该目录中的某处(而不是直接在该目录中)。您需要迭代路径的目录。对于每个目录,使用 -[NSURL getResourceValue:forKey:error:]NSURLFileResourceIdentifierKey 作为获取其资源标识符的键。为垃圾目录获取相同的值。使用 -isEqual: 比较两者。如果您找到资源标识符等于垃圾目录的祖先目录,则该文件在垃圾中。如果祖先目录的迭代到达根目录而没有找到它,那么它就不是。