private static string readdir(IntPtr dir, ref byte[] buffer) { int r = 0; // We can reuse the same buffer since sys_readdir // will fill up the rest of the space by null characters r = sys_readdir(dir, buffer, buffer.Length); if (r == -1) { return(null); } int n_chars = 0; while (n_chars < buffer.Length && buffer [n_chars] != 0) { ++n_chars; } return(FileNameMarshaler.LocalToUTF8(buffer, 0, n_chars)); }
private static unsafe void SnarfWorker() { int event_size = Marshal.SizeOf(typeof(inotify_event)); while (running) { // We get much better performance if we wait a tiny bit // between reads in order to let events build up. // FIXME: We need to be smarter here to avoid queue overflows. Thread.Sleep(15); IntPtr buffer; int nr; // Will block while waiting for events, but with a 1s timeout. inotify_snarf_events(inotify_fd, out nr, out buffer); if (!running) { break; } if (nr == 0) { continue; } ArrayList new_events = new ArrayList(); bool saw_overflow = false; while (nr > 0) { // Read the low-level event struct from the buffer. inotify_event raw_event; raw_event = (inotify_event)Marshal.PtrToStructure(buffer, typeof(inotify_event)); buffer = (IntPtr)((long)buffer + event_size); if ((raw_event.mask & EventType.QueueOverflow) != 0) { saw_overflow = true; } // Now we convert our low-level event struct into a nicer object. QueuedEvent qe = new QueuedEvent(); qe.Wd = raw_event.wd; qe.Type = raw_event.mask; qe.Cookie = raw_event.cookie; // Extract the filename payload (if any) from the buffer. byte [] filename_bytes = new byte[raw_event.len]; Marshal.Copy(buffer, filename_bytes, 0, (int)raw_event.len); buffer = (IntPtr)((long)buffer + raw_event.len); int n_chars = 0; while (n_chars < filename_bytes.Length && filename_bytes [n_chars] != 0) { ++n_chars; } qe.Filename = ""; if (n_chars > 0) { qe.Filename = FileNameMarshaler.LocalToUTF8(filename_bytes, 0, n_chars); } new_events.Add(qe); nr -= event_size + (int)raw_event.len; } if (saw_overflow) { Logger.Log.Warn("Inotify queue overflow!"); } lock (event_queue) { event_queue.AddRange(new_events); Monitor.Pulse(event_queue); } } }