Automatic subtree watching only reacted to `CREATE`, so a directory moved in from elsewhere stayed unwatched. It is now handled like a created one. Items that already exist in such a directory never produce kernel events; they are reported with the same event kind and `synthesized` set to `true`, so consumers can treat them as newly appeared.
59 lines
1.6 KiB
Swift
59 lines
1.6 KiB
Swift
import CInotify
|
|
|
|
struct InotifyEventParser {
|
|
static let readBufferSize = 4096
|
|
|
|
static func parse(fromFileDescriptor fd: Int32) -> [RawInotifyEvent] {
|
|
let buffer = UnsafeMutableRawPointer.allocate(
|
|
byteCount: Self.readBufferSize,
|
|
alignment: MemoryLayout<inotify_event>.alignment
|
|
)
|
|
defer { buffer.deallocate() }
|
|
|
|
let bytesRead = read(fd, buffer, readBufferSize)
|
|
guard bytesRead > 0 else { return [] }
|
|
|
|
return Self.parseEventBuffer(buffer, bytesRead: bytesRead)
|
|
}
|
|
|
|
private static func parseEventBuffer(
|
|
_ buffer: UnsafeMutableRawPointer,
|
|
bytesRead: Int
|
|
) -> [RawInotifyEvent] {
|
|
var events: [RawInotifyEvent] = []
|
|
var offset = 0
|
|
|
|
while offset < bytesRead {
|
|
let eventPointer = buffer.advanced(by: offset)
|
|
let rawEvent = eventPointer.assumingMemoryBound(to: inotify_event.self).pointee
|
|
|
|
events.append(RawInotifyEvent(
|
|
watchDescriptor: rawEvent.wd,
|
|
mask: InotifyEventMask(rawValue: rawEvent.mask),
|
|
cookie: rawEvent.cookie,
|
|
name: Self.extractName(from: eventPointer, nameLength: rawEvent.len),
|
|
synthesized: false
|
|
))
|
|
|
|
offset += Self.eventSize(nameLength: rawEvent.len)
|
|
}
|
|
|
|
return events
|
|
}
|
|
|
|
private static func extractName(
|
|
from eventPointer: UnsafeMutableRawPointer,
|
|
nameLength: UInt32
|
|
) -> String {
|
|
guard nameLength > 0 else { return "" }
|
|
let namePointer = eventPointer
|
|
.advanced(by: MemoryLayout<inotify_event>.size)
|
|
.assumingMemoryBound(to: CChar.self)
|
|
return String(cString: namePointer)
|
|
}
|
|
|
|
private static func eventSize(nameLength: UInt32) -> Int {
|
|
MemoryLayout<inotify_event>.size + Int(nameLength)
|
|
}
|
|
}
|