# 帳票設計書 21-fstat - オープンファイルレポート

## 概要

本ドキュメントは、FreeBSDのfstatコマンドが出力するオープンファイルレポートの帳票設計書である。fstatは全プロセスまたは指定プロセスが開いているファイルの一覧をテキスト形式で標準出力に出力する。

### 本帳票の処理概要

fstatコマンドは、カーネルからプロセスとファイルディスクリプタの情報を取得し、各プロセスが開いているファイルの詳細情報をテーブル形式でレポートする。

**業務上の目的・背景**：システム管理において、どのプロセスがどのファイルをオープンしているかを把握することは、リソースリーク検出、セキュリティ監査、障害解析において必要不可欠である。fstatはこの情報を包括的に表示し、システムの稼働状況を可視化する。

**帳票の利用シーン**：ファイルディスクリプタのリーク調査、特定ファイルを使用しているプロセスの特定、システム全体のオープンファイル状況の監視、アンマウント前のファイル使用状況確認などで使用される。

**主要な出力内容**：
1. ユーザー名（USER）: ファイルを開いているプロセスの所有ユーザー
2. コマンド名（CMD）: プロセスのコマンド名
3. PID: プロセスID
4. ファイルディスクリプタ番号（FD）: ファイルディスクリプタの番号
5. マウントポイント（MOUNT）: ファイルが存在するマウントポイント
6. iノード番号（INUM）: ファイルのiノード番号
7. モード（MODE）: ファイルのアクセスモード（読み/書き/読み書き）
8. リンク数（SZ|DV）: ファイルサイズまたはデバイス番号
9. ファイルフラグ（R/W）: 読み取り/書き込みフラグ
10. ファイル名（NAME）: ファイル名（利用可能な場合）

**帳票の出力タイミング**：システム管理者がコマンドラインからfstatコマンドを実行した時点で即座に出力される。

**帳票の利用者**：システム管理者、セキュリティ監査担当者、障害対応エンジニア

## 帳票種別

一覧表（テキスト形式のテーブル出力）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | コマンドライン | ターミナル | `fstat` コマンド実行 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | テキスト（標準出力） |
| 用紙サイズ | N/A（ターミナル出力） |
| 向き | N/A |
| ファイル名 | N/A（標準出力、リダイレクト可能） |
| 出力方法 | 標準出力（stdout） |
| 文字コード | ロケール依存（通常UTF-8） |

## 帳票レイアウト

### レイアウト概要

fstatの出力はヘッダー行と明細行から構成されるテキストテーブルである。

```
┌─────────────────────────────────────┐
│         ヘッダー行（カラム名）         │
├─────────────────────────────────────┤
│         明細行（1行1ファイル）         │
│         明細行（1行1ファイル）         │
│              ...                    │
└─────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | USER | ファイルを開いているプロセスの所有ユーザー名 | passwd DB (uid -> name変換) | 文字列（左寄せ） |
| 2 | CMD | プロセスのコマンド名 | kinfo_file.kf_comm | 文字列（左寄せ） |
| 3 | PID | プロセスID | kinfo_file.kf_pid | 整数 |
| 4 | FD | ファイルディスクリプタ番号 | kinfo_file.kf_fd | 整数/特殊文字列 |
| 5 | MOUNT | マウントポイント | kinfo_file.kf_path | 文字列 |
| 6 | INUM | iノード番号 | kinfo_file統計情報 | 整数 |
| 7 | MODE | ファイルのアクセスモード | kinfo_file.kf_flags | r/w/rw |
| 8 | SZ|DV | ファイルサイズまたはデバイス番号 | kinfo_file統計情報 | 整数/デバイス番号 |
| 9 | R/W | 読み取り/書き込みフラグ | kinfo_file.kf_flags | r/w/rw |
| 10 | NAME | ファイル名 | kinfo_file.kf_path | 文字列 |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | USER | ユーザー名 | uid_from_pid() | %-8s | 8文字 |
| 2 | CMD | コマンド名 | kinfo_proc | %-10s | 10文字 |
| 3 | PID | プロセスID | kinfo_file | %5d | 5桁 |
| 4 | FD | ファイルディスクリプタ | kinfo_file | %4s | 4文字 |
| 5 | MOUNT | マウントポイント | statfs情報 | 文字列 | 可変 |
| 6 | INUM | iノード番号 | kinfo_file | 整数 | 可変 |
| 7 | MODE | アクセスモード | kinfo_file | 文字列 | 可変 |
| 8 | SZ|DV | サイズ/デバイス | kinfo_file | 整数 | 可変 |

### フッター部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| N/A | なし | フッターは出力されない | - | - |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| -u ユーザー名 | 指定ユーザーのプロセスのみ表示 | No |
| -p PID | 指定プロセスIDのみ表示 | No |
| -f | フラグ情報を追加表示 | No |
| -m | マウントポイントでフィルタ | No |
| -n | 数値表示（UID変換なし） | No |
| -v | 詳細モード | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | PID | 昇順 |
| 2 | FD | 昇順 |

### 改ページ条件

テキスト出力のため改ページなし。ターミナルの表示領域に依存。

## データベース参照仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| kern.proc.filedesc（sysctl） | プロセスのファイルディスクリプタ情報取得 | PIDで指定 |
| kern.proc（sysctl） | プロセス情報取得 | PIDで指定 |
| passwd DB | UID→ユーザー名変換 | UIDをキーに検索 |

### テーブル別参照項目詳細

#### kern.proc.filedesc（sysctl）

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| kf_fd | FD | プロセス単位 | ファイルディスクリプタ番号 |
| kf_type | ファイルタイプ | プロセス単位 | VNODE, SOCKET等 |
| kf_flags | MODE, R/W | プロセス単位 | FREAD, FWRITE等 |
| kf_path | NAME | プロセス単位 | ファイルパス |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| N/A | 計算項目なし | - | カーネルから取得した値をそのまま表示 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[コマンド実行] --> B[オプション解析 getopt]
    B --> C{ユーザー/PID指定?}
    C -->|Yes| D[指定プロセスの情報取得]
    C -->|No| E[全プロセスの情報取得]
    D --> F[ヘッダー出力]
    E --> F
    F --> G[プロセスごとにループ]
    G --> H[ファイルディスクリプタ情報取得]
    H --> I[各FDの情報を整形出力]
    I --> J{次のプロセス?}
    J -->|Yes| G
    J -->|No| K[終了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| 権限エラー | root以外が他ユーザーのプロセスを参照 | 該当プロセスをスキップ | rootで実行 |
| プロセス消失 | 情報取得中にプロセスが終了 | 該当プロセスをスキップ | 正常動作として処理 |
| sysctl失敗 | カーネル情報取得失敗 | エラーメッセージ出力 | システム状態を確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数百〜数万ファイルディスクリプタ |
| 目標出力時間 | 数秒以内 |
| 同時出力数上限 | 制限なし（コマンドの同時実行数に依存） |

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

- root権限がない場合、自プロセスの情報のみ表示される
- カーネル情報へのアクセスにはsysctl経由でアクセス制御が適用される
- 出力にはファイルパス情報が含まれるため、機密ファイルの存在が漏洩する可能性がある

## 備考

- fstatはlibprocstat(3)ライブラリを使用してプロセス情報を取得する
- FreeBSD固有のコマンドであり、Linux等の他のUNIX系OSには同名だが異なる実装が存在する
- main.c (エントリーポイント) と fstat.c (表示処理) に分離された構造を持つ

---

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

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

### 推奨読解順序

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

fstatが扱う主要なデータ構造はlibprocstatが提供するkinfo_file構造体である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | functions.h | `usr.bin/fstat/functions.h` | 表示関数のプロトタイプ宣言。各ファイルタイプ（vnode, socket, pipe等）ごとの表示関数が定義されている |

**読解のコツ**: FreeBSD特有のlibprocstat APIを理解する必要がある。kinfo_file構造体がファイルディスクリプタ1つ分の情報を保持する。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | main.c | `usr.bin/fstat/main.c` | main()関数でオプション解析、プロセス列挙、出力ループを実行 |

**主要処理フロー**:
1. **main.c 行82-130付近**: getopt()によるコマンドラインオプション解析（-u, -p, -f, -m, -n, -v等）
2. **main.c 行130-180付近**: procstat_open_sysctl()でlibprocstatを初期化
3. **main.c 行180-250付近**: procstat_getprocs()で対象プロセス一覧を取得し、各プロセスについてファイルディスクリプタ情報を取得

#### Step 3: 表示処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | fstat.c | `usr.bin/fstat/fstat.c` | 各ファイルタイプごとの詳細表示ロジック |

**主要処理フロー**:
- **fstat.c**: ファイルタイプ（VNODE, SOCKET, PIPE, PTS等）に応じた情報の整形出力

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

```
main() [main.c]
    │
    ├─ getopt() - オプション解析
    │
    ├─ procstat_open_sysctl() - libprocstat初期化
    │
    ├─ procstat_getprocs() - プロセス一覧取得
    │      │
    │      └─ sysctl(kern.proc) - カーネルからプロセス情報取得
    │
    ├─ procstat_getfiles() - FD一覧取得
    │      │
    │      └─ sysctl(kern.proc.filedesc) - カーネルからFD情報取得
    │
    └─ print_file_info() - ファイル情報表示
           │
           ├─ print_vnode_info() - VNODEファイル表示
           ├─ print_socket_info() - ソケット表示
           └─ print_pipe_info() - パイプ表示
```

### データフロー図

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

コマンドライン   ───▶ オプション解析        ───▶ フィルタ条件設定
オプション

kern.proc       ───▶ procstat_getprocs()  ───▶ プロセスリスト
(sysctl)

kern.proc.      ───▶ procstat_getfiles()  ───▶ FDリスト
filedesc(sysctl)

passwd DB       ───▶ UID→名前変換         ───▶ ユーザー名
                                               │
                                               ▼
                                          標準出力
                                          (テーブル形式)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| main.c | `usr.bin/fstat/main.c` | ソース | エントリーポイント、プロセス列挙ループ |
| fstat.c | `usr.bin/fstat/fstat.c` | ソース | ファイル情報の表示処理 |
| functions.h | `usr.bin/fstat/functions.h` | ヘッダー | 表示関数のプロトタイプ宣言 |
| Makefile | `usr.bin/fstat/Makefile` | ビルド | ビルド設定、リンクライブラリ指定 |
