A directory moved out of a watched tree kept its kernel watches, so later changes inside it were reported under the old path. Its watches and those of its subdirectories are now removed on `MOVED_FROM`. Watches the kernel reports as `IGNORED` are forgotten as well, so a reused descriptor number cannot map to a stale path.
55 lines
1.9 KiB
Swift
55 lines
1.9 KiB
Swift
struct InotifyWatchManager {
|
|
private var watchPaths: [CInt: String] = [:]
|
|
private var watchMasks: [CInt: InotifyEventMask] = [:]
|
|
private var activeWatches: Set<CInt> = []
|
|
private var watchesWithAutomaticSubtreeWatching: Set<CInt> = []
|
|
|
|
mutating func add(_ path: String, withId watchDescriptor: CInt, mask: InotifyEventMask) {
|
|
self.watchPaths[watchDescriptor] = path
|
|
self.watchMasks[watchDescriptor] = mask
|
|
self.activeWatches.insert(watchDescriptor)
|
|
}
|
|
|
|
mutating func enableAutomaticSubtreeWatching(forId watchDescriptor: CInt) {
|
|
assert(self.activeWatches.contains(watchDescriptor))
|
|
self.watchesWithAutomaticSubtreeWatching.insert(watchDescriptor)
|
|
}
|
|
|
|
mutating func enableAutomaticSubtreeWatching(forIds watchDescriptors: CInt...) {
|
|
self.enableAutomaticSubtreeWatching(forIds: watchDescriptors)
|
|
}
|
|
|
|
mutating func enableAutomaticSubtreeWatching(forIds watchDescriptors: [CInt]) {
|
|
for watchDescriptor in watchDescriptors {
|
|
self.enableAutomaticSubtreeWatching(forId: watchDescriptor)
|
|
}
|
|
}
|
|
|
|
mutating func remove(forId watchDescriptor: CInt) {
|
|
self.watchPaths.removeValue(forKey: watchDescriptor)
|
|
self.watchMasks.removeValue(forKey: watchDescriptor)
|
|
self.activeWatches.remove(watchDescriptor)
|
|
self.watchesWithAutomaticSubtreeWatching.remove(watchDescriptor)
|
|
}
|
|
|
|
func path(forId watchDescriptor: CInt) -> String? {
|
|
return self.watchPaths[watchDescriptor]
|
|
}
|
|
|
|
/// The descriptors of the watch on `path` itself and of every watch below it.
|
|
func descriptors(under path: String) -> [CInt] {
|
|
let prefix = path.hasSuffix("/") ? path : path + "/"
|
|
return self.watchPaths
|
|
.filter { $0.value == path || $0.value.hasPrefix(prefix) }
|
|
.map(\.key)
|
|
}
|
|
|
|
func mask(forId watchDescriptor: CInt) -> InotifyEventMask? {
|
|
return self.watchMasks[watchDescriptor]
|
|
}
|
|
|
|
func isAutomaticSubtreeWatching(_ watchDescriptor: CInt) -> Bool {
|
|
return self.watchesWithAutomaticSubtreeWatching.contains(watchDescriptor)
|
|
}
|
|
}
|