# FSEvent - Cross-Platform File System Monitoring

## Overview

FSEvent provides file system monitoring across Linux (fanotify), macOS (FSEvents), and Windows. Features configuration testing, working flag detection, depth control, and exclude path filtering.

## Configuration System

The system detects working configurations:

### Linux (fanotify)

The `createWorkingFanotifyAndStartMonitoring()` function finds working flag combinations:

- **Init Flags**: Tested from `FAN_REPORT_FID` (required for non-root)
- **Mark Flags**: `FAN_MARK_ADD` (basic monitoring)
- **Event Mask**: Tested from `FAN_MODIFY | FAN_CREATE | FAN_DELETE`
- **File Path Support**: `FAN_REPORT_DFID_NAME_TARGET`

### Working Configuration

- **Mark Flags**: `FAN_MARK_ADD` (0x1) - Basic monitoring
- **Event Mask**: `0x58001f3f` - Event set
- **Init Flags**: `0x1e03` - File handle reporting + directory + filename support
- **File Path Support**: `FAN_REPORT_DFID_NAME_TARGET`

## System Compatibility

### Platform Support

#### Linux (fanotify)

- <https://man7.org/linux/man-pages/man7/fanotify.7.html>
- <https://man7.org/linux/man-pages/man2/fanotify_init.2.html>
- <https://man7.org/linux/man-pages/man2/fanotify_mark.2.html>
- <https://codebrowser.dev/linux/include/linux/fanotify.h.html>
- <https://lpc.events/event/18/contributions/1717/attachments/1648/3404/fanotify.pdf>

- Supports modern filesystems (ext4, xfs, btrfs, etc.)
- Automatic configuration detection
- Non-root user compatibility
- File path reporting

#### macOS (FSEvents)

- Native filesystem event monitoring with simplified event classification
- Unicode path support
- Aggressive noise filtering to eliminate build system artifacts
- Logical event ordering for complex flag combinations
- Platform-specific filtering for directory-only and metadata-only events

#### Windows

- Unicode support with accurate file-level event detection
- Overlapped I/O for asynchronous, responsive event processing
- Immediate event processing to preserve chronological order
- Network path filtering to prevent false positives from network drive access
- <https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf/fileapi-readdirectorychangesw>

## Architecture

**Lua Implementation Files:**

- `fsevent-common.lua` - Cross-platform event processing logic
- `fsevent-mac.lua` - macOS FSEvents implementation
- `fsevent-linux.lua` - Linux fanotify implementation
- `fsevent-win.lua` - Windows ReadDirectoryChangesW implementation
- `fsevent.lua` - Main API wrapper

**Core Functions:**

- `eventCallback()` - Unified event processing with platform-specific filtering
- Platform-specific noise filtering and event ordering
- Smart timeout handling for event accumulation

## Event Batching Behavior

### Platform-Specific Batching

Different operating systems handle file system event batching differently before calling Lua callbacks:

#### macOS (FSEvents)

- **Native System Batching**: FSEvents framework batches events at the kernel level
- **System Call**: `FSEventStreamCreate()` with configurable `latency` parameter
- **Efficiency**: Most efficient - OS handles grouping, reduces system calls
- **Callback Timing**: Events delivered after latency timeout expires

#### Linux (fanotify)

- **System Call**: Individual `fanotify` events via `read()` system calls with smart timeout
- **Event Processing**: Immediate deduplication vs previous event with timeout-based flushing
- **Memory Safety**: Single-event processing with dedicated path copying
- **Kernel Filtering**: Excludes paths handled at kernel level

#### Windows (ReadDirectoryChangesW)

- **System Call**: `ReadDirectoryChangesW()` with overlapped I/O and smart timeout
- **Event Processing**: Immediate deduplication vs previous event with timeout-based flushing
- **Thread Safety**: Single-event processing prevents event loss during rapid changes
- **Memory Safety**: Single-event processing with dedicated path copying
- **Network Filtering**: Automatic filtering of network drive access events

### Performance Implications

- **Simplified Architecture**: All platforms use immediate deduplication with single previous event
- **Smart Timeouts**: OS-level timeout integration ensures no event loss or hanging
- **Memory Efficiency**: Single-event processing eliminates array overhead and batching delays
- **Responsiveness**: Immediate event deduplication vs previous event with guaranteed delivery
- **Event Ordering**: All platforms maintain chronological event sequence
- **Consistency**: Same behavior and reliability across all platforms

### Flush Mechanism

The flush mechanism enables responsive event handling for rapid file changes while maintaining efficiency for idle periods.

#### How It Works

**Event Accumulation:**

Events are accumulated during `eventAccumulationTimeout` (default 0.1s):

- Same file events combined via bitwise OR on flags
- Different file events flush previous accumulated event
- Delete/rename events flush immediately

**Callback Return Value Control:**

The callback in `fsevent-common.lua` returns values to control event flow:

- **Return 0** - Continue monitoring, no pending events (next wait uses infinite timeout)
- **Return 1** - Stop requested immediately
- **Return 2** - Has pending events, trigger short timeout to flush

**Platform Loop Pattern:**

Each platform implements this flush pattern:

```lua
while not stopRequested do
  hasPendingEvent = false  -- Reset at start of each iteration
  local timeout = getTimeoutForEventWait()  -- Short if had pending events
  -- Wait for event with calculated timeout...
  -- Process events (callback may return 2)

  if hasPendingEvent then
    eventCallback({timeout = true})  -- Trigger flush of accumulated events
  end
  -- Loop continues, next iteration uses short timeout if events were flushed
end
```

**Smart Timeout Calculation:**

```lua
function getTimeoutForEventWait()
  if lastEventWasRealEvent then
    -- Short timeout to catch rapid follow-up events
    return math.floor(eventAccumulationTimeout * 1000)  -- 100ms
  end
  if stopTimeout and stopTimeout > 0 then
    return math.floor(stopTimeout * 1000)  -- Overall stop timeout
  end
  -- No recent activity, wait indefinitely
  return 0xFFFFFFFF  -- Infinite wait
end
```

**Flow Example:**

1. File change occurs → `eventCallback` processes event → `hasPendingEvent = true`
2. Callback returns 2 → Platform sets `hasPendingEvent = true`
3. After event loop, platform sends `{timeout = true}` event
4. `eventCallback` flushes accumulated events via `flushAllPendingEvents()`
5. `lastEventWasRealEvent = true` → Next iteration uses 100ms timeout
6. If more events occur within 100ms → Caught and flushed
7. If no events → `lastEventWasRealEvent = false` → Next iteration waits indefinitely

This ensures rapid follow-up events are caught quickly while idle periods don't waste CPU cycles.

### Event Display Ordering

**Logical Sequence**: Events displayed in chronological order:

1. `create` → File creation
2. `open` → File opening
3. `access` → File reading
4. `execute` → File execution
5. `modify` → Content changes
6. `metadata/inode/owner` → Attribute changes
7. `rename` → File renaming
8. `close` → File closing
9. `remove` → File deletion
10. `dir/child` → Context information

## Features

- Automatic configuration detection
- Unified error handling
- Cross-platform compatibility
- Common event processing system
- Accurate Windows file-level detection
- Logical event ordering across all platforms
- Network path filtering
- Build system noise filtering
- OS-specific event batching optimization
- Depth control
- Exclude path filtering
- File path support
- Responsive event processing

## Finding Dead Code (C++ Reference)

### Best Tool: cppcheck

```bash
# Find ALL unused functions across entire project (exhaustive analysis)
cppcheck --enable=unusedFunction --check-level=exhaustive .
```

**Why cppcheck is better than GCC:**

- Cross-file analysis (finds functions defined but never used anywhere)
- More comprehensive dead code detection with `--check-level=exhaustive`
- Doesn't miss functions like GCC's `-Wunused-function`
- Analyzes all code paths and branch conditions thoroughly

### Alternative: GCC Analysis

```bash
# Find dead code within single file only (limitations)
g++ -Wall -Wextra -Wunused -Wunused-function -Wunused-variable -Wunused-parameter -Wunreachable-code -c file.cpp -o /dev/null
```

**GCC Limitations:**

- Only analyzes single file, can't detect functions called from other files
- Misses functions like `createDirectoryErrorMessage()` that are defined but never called
- Use cppcheck for complete dead code detection

### Warning Meanings

- `unused function`: Function exists but never called
- `unused variable`: Variable declared but never read
- `unused parameter`: Function parameter never used
- `unreachable code`: Code after return/break that never executes

## C++ Build Reference

### Build Commands

```bash
# xmake
xmake

# Linux
g++ -std=c++17 -D__linux__ fsevent.cpp fsevent-common.cpp -o fsevent

# macOS
clang++ -std=c++17 fsevent.cpp fsevent-common.cpp -o fsevent -framework CoreFoundation -framework CoreServices

# Windows
g++ -m64 -O2 -fPIC -shared -o fsevent.dll fsevent-win.cpp fsevent-common.cpp
```

### Configuration Detection Output

```text
=== Creating working fanotify fd and starting monitoring ===
Testing base flag FAN_REPORT_FID (0x200)
Base flag works, testing additional flags
Flag 0x100 (FAN_REPORT_DFID_NAME_TARGET) works
Created working fanotify fd=3 with flags=0x1e03
Starting with FAN_MARK_ADD and basic events
Basic marking works, testing additional event flags
Added event flag 0x1, 0x4, 0x8, 0x10, 0x20, 0x1000, 0x40000000, 0x8000000, 0x10000000, 0x400, 0x800
Applying working configuration to all directories
Marking directory: /path/to/monitor
Successfully marked directory: /path/to/monitor
=== SUCCESS: Created working fanotify fd=3 ===
Final configuration: markFlag=0x1, eventMask=0x58001f3f, initFlag=0x1e03
File path support enabled (FAN_REPORT_DFID_NAME_TARGET)
```

### Implementation Files

**Common Code:**

- `fsevent-common.h` - Shared structures and function declarations
- `fsevent-common.cpp` - Cross-platform functionality

**Helper Functions:**

- `returnMessage()` - Standardized message formatting
- `printError()` - Standardized error formatting
- `allocateAndCopyPath()` - Safe path string allocation
- `debugPrint()` - Conditional debug output
- `checkDirectory()` - Directory validation
- `createWorkingFanotifyAndStartMonitoring()` - Configuration detection

**Platform-Specific:**

- `fsevent.cpp` - Linux fanotify and macOS FSEvents implementation
- `fsevent-win.cpp` - Windows ReadDirectoryChangesW implementation
