# 通知設計書 17-Interop.Sys.INotify (IN_ATTRIB)

## 概要

本ドキュメントは、Linux の inotify サブシステムが提供する `IN_ATTRIB` 通知について、.NET ランタイムでの実装詳細と設計仕様を記述した通知設計書である。

### 本通知の処理概要

IN_ATTRIB は、ファイルの属性（メタデータ）が変更された際に Linux カーネルの inotify サブシステムが生成する通知イベントである。.NET の FileSystemWatcher では、この通知を Changed イベントに変換してアプリケーションに通知する。

**業務上の目的・背景**：ファイル属性の変更検知は、パーミッション変更の監視、所有者変更のセキュリティ監査、リンクカウント変更の追跡、拡張属性の変更検知など、システム管理やセキュリティ関連の業務シナリオで必要とされる。IN_ATTRIB は NotifyFilters で Attributes、CreationTime、LastAccess、LastWrite、Security、Size のいずれかが設定されている場合に有効となる。

**通知の送信タイミング**：監視対象のファイルまたはディレクトリの属性（パーミッション、所有者、タイムスタンプ、リンクカウントなど）が変更された際に、カーネルが inotify イベントを生成する。このイベントは .NET の FileSystemWatcher.Linux 実装で処理され、Changed イベントとしてアプリケーションに通知される。

**通知の受信者**：FileSystemWatcher インスタンスの Changed イベントにハンドラを登録したアプリケーションコード。NotifyFilters に上記のフィルタのいずれかが含まれている必要がある。

**通知内容の概要**：inotify イベントとして、ウォッチ記述子（wd）、イベントマスク（IN_ATTRIB）、cookie（通常0）、ファイル名（name）が通知される。FileSystemWatcher は WatcherChangeTypes.Changed としてアプリケーションに伝達する。

**期待されるアクション**：受信者は通知を受け取り後、パーミッション検証、セキュリティアラートの発報、監査ログの記録、キャッシュの無効化などの処理を実行することが期待される。

## 通知種別

OSカーネル通知（inotify イベント）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（カーネルからの割り込み） |
| 優先度 | 通常（他の inotify イベントと同等） |
| リトライ | なし（カーネルは一度のみ通知） |

### 送信先決定ロジック

inotify_add_watch() で登録されたウォッチ記述子に対応する inotify ファイルディスクリプタに対してイベントが送信される。.NET では INotify クラスが全ての FileSystemWatcher で共有する単一の inotify インスタンスを管理する。

## 通知テンプレート

### inotify イベント構造

| 項目 | 内容 |
|-----|------|
| イベント型 | struct inotify_event |
| マスク値 | IN_ATTRIB (0x00000004) |
| cookie | 0（ペアイベントではない） |

### イベントデータ構造

```c
struct inotify_event {
    int      wd;       // ウォッチ記述子
    uint32_t mask;     // IN_ATTRIB = 0x00000004
    uint32_t cookie;   // 0
    uint32_t len;      // name の長さ
    char     name[];   // ファイル名（NULL終端）
};
```

### .NET での変換後

```csharp
// IN_ATTRIB は Changed イベントに変換される
FileSystemEventArgs {
    ChangeType = WatcherChangeTypes.Changed,
    FullPath = "監視ディレクトリ/ファイル名",
    Name = "ファイル名"
}
```

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| wd | ウォッチ記述子 | inotify_add_watch() の戻り値 | Yes |
| mask | イベントマスク | IN_ATTRIB (0x00000004) | Yes |
| cookie | イベント関連付け | 常に 0 | Yes |
| len | 名前長 | ファイル名のバイト長 + パディング | Yes |
| name | ファイル名 | 対象ファイルの名前 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| システムコール | chmod() | ウォッチにIN_ATTRIBが設定されている | パーミッション変更時 |
| システムコール | chown() | ウォッチにIN_ATTRIBが設定されている | 所有者変更時 |
| システムコール | utimes()/utime() | ウォッチにIN_ATTRIBが設定されている | タイムスタンプ変更時 |
| システムコール | link()/unlink() | ウォッチにIN_ATTRIBが設定されている | リンクカウント変更時 |
| システムコール | setxattr()/removexattr() | ウォッチにIN_ATTRIBが設定されている | 拡張属性変更時 |

### .NET での有効化条件

| 条件 | 説明 |
|-----|------|
| NotifyFilters.Attributes | このフィルタで IN_ATTRIB が有効化 |
| NotifyFilters.CreationTime | このフィルタで IN_ATTRIB が有効化 |
| NotifyFilters.LastAccess | このフィルタで IN_ATTRIB が有効化 |
| NotifyFilters.LastWrite | このフィルタで IN_ATTRIB が有効化 |
| NotifyFilters.Security | このフィルタで IN_ATTRIB が有効化 |
| NotifyFilters.Size | このフィルタで IN_ATTRIB が有効化 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| NotifyFilters に該当フィルタなし | 上記6つのいずれも設定されていない場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[chmod/chown 等実行] --> B[カーネル: inotify イベント生成]
    B --> C[inotify キューに追加]
    C --> D[.NET: ProcessEvents スレッド]
    D --> E[TryReadEvent でイベント読み取り]
    E --> F{mask & IN_ATTRIB?}
    F -->|Yes| G[WatcherEvent.Changed 生成]
    F -->|No| H[他のイベント処理]
    G --> I[_eventQueue に追加]
    I --> J[EmitEvent]
    J --> K[fsw.NotifyFileSystemEventArgs]
    K --> L[OnChanged 呼び出し]
    L --> M[終了]
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（OSカーネル通知のためデータベースを使用しない）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| IN_Q_OVERFLOW | inotify イベントキューが溢れた | Error イベント発生、監視再起動 |
| EBADF | 無効なファイルディスクリプタ | 監視を停止 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（カーネルイベントはリトライされない） |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | カーネル設定依存（/proc/sys/fs/inotify/max_queued_events） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（24時間監視可能）

## セキュリティ考慮事項

- IN_ATTRIB はパーミッション変更を検知できるため、セキュリティ監査に有用
- 監視対象ディレクトリへの読み取り権限が必要
- 変更後の属性値は通知に含まれない（変更があったことのみ通知）

## 備考

- IN_ATTRIB はファイル内容の変更なしにメタデータのみ変更された場合に発生
- touch コマンドでタイムスタンプ変更時も IN_ATTRIB が発生
- ハードリンクの作成/削除でリンクカウントが変化すると IN_ATTRIB が発生
- ディレクトリの属性変更でも IN_ATTRIB が発生する

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、IN_ATTRIB の定義と関連する定数を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Interop.INotify.cs | `src/libraries/Common/src/Interop/Linux/System.Native/Interop.INotify.cs` | IN_ATTRIB 定数の定義（0x00000004） |

**読解のコツ**: NotifyEvents enum で IN_ATTRIB = 0x00000004 として定義されている点に注目。

#### Step 2: フィルタマッピングを理解する

NotifyFilters から inotify イベントへの変換ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | FileSystemWatcher.Linux.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs` | TranslateFilters メソッドでの IN_ATTRIB マッピング |

**主要処理フロー**:
- **行 1268-1274 (Linux.cs)**: filtersForAttrib に6つのフィルタが含まれる（Attributes、CreationTime、LastAccess、LastWrite、Security、Size）
- **行 1283-1286 (Linux.cs)**: IN_ATTRIB をサブスクライブする条件判定

#### Step 3: イベント処理を理解する

IN_ATTRIB イベントの処理フローを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FileSystemWatcher.Linux.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs` | ProcessEvent での IN_ATTRIB 処理 |

**主要処理フロー**:
- **行 527-529 (Linux.cs)**: EventMask に IN_ATTRIB が含まれる定義
- **行 685-688 (Linux.cs)**: IN_ATTRIB イベントで WatcherEvent.Changed を生成

### プログラム呼び出し階層図

```
[Linux カーネル]
inotify イベント (IN_ATTRIB)
    │
    ▼
[.NET FileSystemWatcher.Linux]
INotify.ProcessEvents()
    │
    ├─ TryReadEvent() → NotifyEvent 構造体
    │
    └─ ProcessEvent()
           │
           ├─ mask & IN_ATTRIB 判定
           │
           └─ WatcherEvent.Changed(dir, name)
                  │
                  ▼
           Watcher.QueueEvent()
                  │
                  ▼
           EmitEvent()
                  │
                  ▼
           fsw.NotifyFileSystemEventArgs(Changed, name)
                  │
                  ▼
           OnChanged()
```

### データフロー図

```
[入力]                    [処理]                           [出力]

chmod/chown             カーネル inotify
システムコール  ───▶    イベント生成  ───▶   inotify キュー
                              │
                              ▼
                        .NET read() ───▶   NotifyEvent 構造体
                              │
                              ▼
                        ProcessEvent()
                              │
                              ▼
                        WatcherEvent.Changed
                              │
                              ▼
                        FileSystemEventArgs ───▶  Changed イベント
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Interop.INotify.cs | `src/libraries/Common/src/Interop/Linux/System.Native/Interop.INotify.cs` | ソース | IN_ATTRIB 定数定義 |
| FileSystemWatcher.Linux.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs` | ソース | IN_ATTRIB イベント処理、TranslateFilters |
| FileSystemWatcher.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs` | ソース | NotifyFilters、Changed イベント定義 |
