# 機能設計書 6-open_read_only

## 概要

本ドキュメントは、Hack Standard Library (HSL) のファイル操作モジュール `HH\Lib\File\open_read_only` 関数の機能設計書である。

### 本機能の処理概要

**業務上の目的・背景**：
ファイルシステムからデータを読み取ることは、設定ファイルの読み込み、ログファイルの解析、データファイルの処理など、多くのアプリケーションで必要とされる基本的な操作である。`open_read_only`関数は、ファイルを読み取り専用モードで安全に開き、非同期読み取り操作が可能なハンドルを返す。読み取り専用で開くことで、誤ってファイルを変更するリスクを排除し、より安全なファイル操作を実現する。

**機能の利用シーン**：
- 設定ファイル（JSON、YAML、INI等）の読み込み
- ログファイルの解析・モニタリング
- 静的アセット（テンプレート、リソース）の読み込み
- データファイル（CSV、固定長）の処理
- バイナリファイルの読み取り

**主要な処理内容**：
1. 指定されたパスのファイルをOS\O_RDONLYモードで開く
2. ファイルディスクリプタを取得
3. CloseableReadHandleインスタンスを作成して返却
4. ハンドルを通じて非同期読み取り操作を提供

**関連システム・外部連携**：
- `OS\open()`関数でファイルを開く
- `_File\CloseableReadHandle`クラスでハンドルをラップ
- `IO`名前空間のReadHandle関連インターフェースを実装

**権限による制御**：ファイルシステムのパーミッションに依存

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 画面なし | - | 本プロジェクトはUIを持たないライブラリのため該当なし |

## 機能種別

ファイルI/O / 読み取り操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| path | string | Yes | 開くファイルのパス | 有効なファイルパス |

### 入力データソース

- プログラムから直接呼び出し（API）
- ファイルシステム上の既存ファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | CloseableReadHandle | 読み取り操作が可能なファイルハンドル |

### 出力先

- 呼び出し元プログラムへの戻り値

## 処理フロー

### 処理シーケンス

```
1. open_read_only($path)が呼び出される
   └─ ファイルパスを受け取る
2. OS\open()でファイルを開く
   └─ フラグ: OS\O_RDONLY（読み取り専用）
   └─ FileDescriptorを取得
3. CloseableReadHandleを作成
   └─ FileDescriptorとパスを渡す
4. ハンドルを返却
   └─ 呼び出し元で読み取り操作を実行可能
```

### フローチャート

```mermaid
flowchart TD
    A[open_read_only開始] --> B[OS::open呼び出し]
    B --> C{ファイルが存在?}
    C -->|No| D[ErrnoException: ENOENT]
    C -->|Yes| E{読み取り権限あり?}
    E -->|No| F[ErrnoException: EACCES]
    E -->|Yes| G[FileDescriptor取得]
    G --> H[CloseableReadHandle作成]
    H --> I[ハンドルを返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 読み取り専用 | ファイルは読み取り専用で開かれ、書き込みは不可 | 常時 |
| BR-02 | 既存ファイル必須 | 指定されたパスにファイルが存在する必要がある | 常時 |
| BR-03 | パーミッションチェック | 実行ユーザーに読み取り権限が必要 | 常時 |
| BR-04 | クローズ責任 | 呼び出し元がclose()またはcloseWhenDisposed()を呼ぶ責任を持つ | 常時 |

### 計算ロジック

該当なし

## データベース操作仕様

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ENOENT | OS\ErrnoException | ファイルが存在しない | 正しいパスを指定する |
| EACCES | OS\ErrnoException | 読み取り権限がない | ファイルのパーミッションを確認 |
| EISDIR | OS\ErrnoException | パスがディレクトリ | ファイルパスを指定する |
| EMFILE | OS\ErrnoException | プロセスのFD上限に達した | ファイルを適切にclose |
| ENFILE | OS\ErrnoException | システムのFD上限に達した | システム設定を確認 |

### リトライ仕様

本機能自体にリトライ機構は組み込まれていない。

## トランザクション仕様

該当なし

## パフォーマンス要件

- ファイルオープンはOSのシステムコールに依存
- ハンドル作成のオーバーヘッドは最小限
- 大量のファイルを開く場合はFD上限に注意

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

- ファイルパスのバリデーション（パストラバーサル対策）は呼び出し元の責任
- シンボリックリンクを経由した意図しないファイルアクセスに注意
- センシティブなファイルへのアクセス制御はOS権限で行う

## 備考

- 非推奨の`open_read_only_nd`関数が存在するが、`open_read_only`を使用すること
- ハンドルはシーク可能（SeekableReadFDHandle）
- `getPath()`でファイルパスを取得可能
- `getSize()`でファイルサイズを取得可能

---

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

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

### 推奨読解順序

#### Step 1: 関数シグネチャを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | open.php | `src/file/open.php` | open_read_only関数（14-17行目） |

**読解のコツ**: パイプライン演算子`|>`で処理の流れを追う。

**主要処理フロー**:
- **15行目**: `OS\open($path, OS\O_RDONLY)` - OSレベルでファイルを開く
- **16行目**: `new _File\CloseableReadHandle($$, $path)` - ハンドルを作成

#### Step 2: ハンドルインターフェースを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Handle.php | `src/file/Handle.php` | インターフェース定義（15-56行目） |
| 2-2 | CloseableHandle.php | `src/file/CloseableHandle.php` | クローズ可能なハンドルのインターフェース |

**主要なインターフェース**:
- **15-19行目**: `Handle` - 基本インターフェース（getPath, getSize, lock, tryLockx）
- **48-49行目**: `ReadHandle` - 読み取りハンドルインターフェース
- **18-20行目**: `CloseableReadHandle` - クローズ可能な読み取りハンドル

#### Step 3: ハンドル実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | CloseableReadHandle.php | `src/file/_Private/CloseableReadHandle.php` | 実装クラス（16-20行目） |
| 3-2 | CloseableFileHandle.php | `src/file/_Private/CloseableFileHandle.php` | 基底クラス（18-68行目） |

**主要処理フロー**:
- **16-20行目**: `CloseableReadHandle`はCloseableFileHandleを継承
- **19行目**: `FileDescriptorReadHandleTrait`を使用
- **30-32行目**: `getPath()` - ファイルパスを返却
- **34-40行目**: `getSize()` - ファイルサイズを取得

#### Step 4: 読み取りトレイトを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | FileDescriptorReadHandleTrait.php | `src/io/_Private/FileDescriptorReadHandleTrait.php` | 読み取り機能の実装 |

**読解のコツ**: トレイトは複数のクラスに共通機能を提供する。

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

```
File\open_read_only($path)
    |
    +-- OS\open($path, OS\O_RDONLY)
    |       |
    |       +-- FileDescriptor を返却
    |
    +-- new _File\CloseableReadHandle($fd, $path)
            |
            +-- extends CloseableFileHandle
            |       |
            |       +-- extends _IO\FileDescriptorHandle
            |
            +-- use _IO\FileDescriptorReadHandleTrait
                    |
                    +-- readAllowPartialSuccessAsync()
                    +-- readAllAsync()
                    +-- readImpl()
```

### データフロー図

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

string $path
    |
    v
┌─────────────────────────────────────────────────────────────┐
│ OS\open($path, O_RDONLY)                                    │
│   - システムコールでファイルを開く                           │
│   - FileDescriptor を取得                                   │
└─────────────────────────────────────────────────────────────┘
    |
    v
┌─────────────────────────────────────────────────────────────┐
│ CloseableReadHandle($fd, $path)                             │
│   - ファイルディスクリプタをラップ                           │
│   - 読み取り操作を提供                                       │
│     - readAllowPartialSuccessAsync()                        │
│     - readAllAsync()                                        │
│     - seek() / tell()                                       │
└─────────────────────────────────────────────────────────────┘
    |
    v
CloseableReadHandle ──────────> 読み取りデータ (string)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| open.php | `src/file/open.php` | ソース | open_read_only関数の定義 |
| Handle.php | `src/file/Handle.php` | ソース | ファイルハンドルのインターフェース |
| CloseableHandle.php | `src/file/CloseableHandle.php` | ソース | クローズ可能ハンドルのインターフェース |
| CloseableReadHandle.php | `src/file/_Private/CloseableReadHandle.php` | ソース | 読み取りハンドルの実装 |
| CloseableFileHandle.php | `src/file/_Private/CloseableFileHandle.php` | ソース | ファイルハンドルの基底実装 |
| FileDescriptorReadHandleTrait.php | `src/io/_Private/FileDescriptorReadHandleTrait.php` | ソース | 読み取り機能のトレイト |
| FileTest.php | `tests/file/FileTest.php` | テスト | ファイル操作のテスト |
