private bool TryReadEvent(out NotifyEvent notifyEvent)
{
Debug.Assert(_buffer != null);
Debug.Assert(_bufferAvailable >= 0 && _bufferAvailable <= _buffer.Length);
Debug.Assert(_bufferPos >= 0 && _bufferPos <= _bufferAvailable);
// Read more data into our buffer if we need it
if (_bufferAvailable == 0 || _bufferPos == _bufferAvailable)
{
// Read from the handle. This will block until either data is available
// or all watches have been removed, in which case zero bytes are read.
unsafe
{
try
{
fixed (byte* buf = this._buffer)
{
_bufferAvailable = Interop.CheckIo(Interop.Sys.Read(_inotifyHandle, buf, this._buffer.Length),
isDirectory: true);
Debug.Assert(_bufferAvailable <= this._buffer.Length);
}
}
catch (ArgumentException)
{
_bufferAvailable = 0;
Debug.Fail("Buffer provided to read was too small");
}
Debug.Assert(_bufferAvailable >= 0);
}
if (_bufferAvailable == 0)
{
notifyEvent = default(NotifyEvent);
return false;
}
Debug.Assert(_bufferAvailable >= c_INotifyEventSize);
_bufferPos = 0;
}
// Parse each event:
// struct inotify_event {
// int wd;
// uint32_t mask;
// uint32_t cookie;
// uint32_t len;
// char name[]; // length determined by len; at least 1 for required null termination
// };
Debug.Assert(_bufferPos + c_INotifyEventSize <= _bufferAvailable);
NotifyEvent readEvent;
readEvent.wd = BitConverter.ToInt32(_buffer, _bufferPos);
readEvent.mask = BitConverter.ToUInt32(_buffer, _bufferPos + 4); // +4 to get past wd
readEvent.cookie = BitConverter.ToUInt32(_buffer, _bufferPos + 8); // +8 to get past wd, mask
int nameLength = (int)BitConverter.ToUInt32(_buffer, _bufferPos + 12); // +12 to get past wd, mask, cookie
readEvent.name = ReadName(_bufferPos + c_INotifyEventSize, nameLength); // +16 to get past wd, mask, cookie, len
_bufferPos += c_INotifyEventSize + nameLength;
notifyEvent = readEvent;
return true;
}