# 機能設計書 7-open_write_only

## 概要

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

### 本機能の処理概要

**業務上の目的・背景**：
ファイルへのデータ出力は、ログの記録、レポートの生成、設定ファイルの更新、データのエクスポートなど、多くのアプリケーションで必要とされる基本的な操作である。`open_write_only`関数は、ファイルを書き込み専用モードで開き、非同期書き込み操作が可能なハンドルを返す。`WriteMode`列挙型により、ファイルの作成・上書き・追記などの動作を柔軟に制御できる。

**機能の利用シーン**：
- ログファイルへの追記出力
- レポートファイルの新規作成
- 設定ファイルの更新（上書き）
- データのエクスポート・バックアップ
- 一時ファイルへの書き込み

**主要な処理内容**：
1. 指定されたパスのファイルをOS\O_WRONLYモードと指定されたWriteModeで開く
2. ファイルが存在しない場合、WriteModeに応じて新規作成
3. ファイル作成時のパーミッションを指定可能
4. CloseableWriteHandleインスタンスを作成して返却

**関連システム・外部連携**：
- `OS\open()`関数でファイルを開く
- `_File\CloseableWriteHandle`クラスでハンドルをラップ
- `WriteMode`列挙型でオープンモードを制御

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

## 関連画面

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

## 機能種別

ファイルI/O / 書き込み操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| path | string | Yes | 開くファイルのパス | 有効なファイルパス |
| mode | WriteMode | No | オープンモード（デフォルト: OPEN_OR_CREATE） | WriteMode列挙値 |
| create_file_permissions | int | No | 新規作成時のパーミッション（デフォルト: 0644） | 有効なUnixパーミッション |

### 入力データソース

- プログラムから直接呼び出し（API）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | CloseableWriteHandle | 書き込み操作が可能なファイルハンドル |

### 出力先

- 呼び出し元プログラムへの戻り値
- 指定されたファイルパス（書き込み先）

## 処理フロー

### 処理シーケンス

```
1. open_write_only($path, $mode, $create_file_permissions)が呼び出される
   └─ デフォルト値: mode=OPEN_OR_CREATE, permissions=0644
2. OS\open()でファイルを開く
   └─ フラグ: OS\O_WRONLY | $mode as int
   └─ O_CREATフラグがある場合はpermissionsを渡す
3. CloseableWriteHandleを作成
   └─ FileDescriptorとパスを渡す
4. ハンドルを返却
   └─ 呼び出し元で書き込み操作を実行可能
```

### フローチャート

```mermaid
flowchart TD
    A[open_write_only開始] --> B{WriteMode判定}
    B --> C[O_WRONLY | mode フラグ生成]
    C --> D{O_CREATを含む?}
    D -->|Yes| E[permissions引数付きでOS::open]
    D -->|No| F[OS::open]
    E --> G{ファイル操作成功?}
    F --> G
    G -->|No| H[ErrnoException]
    G -->|Yes| I[FileDescriptor取得]
    I --> J[CloseableWriteHandle作成]
    J --> K[ハンドルを返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 書き込み専用 | ファイルは書き込み専用で開かれ、読み取りは不可 | 常時 |
| BR-02 | モード別動作 | WriteModeにより作成・上書き・追記の動作が決まる | 常時 |
| BR-03 | パーミッション適用 | O_CREATフラグがある場合のみpermissionsが適用される | ファイル新規作成時 |
| BR-04 | クローズ責任 | 呼び出し元がclose()またはcloseWhenDisposed()を呼ぶ責任を持つ | 常時 |

### WriteMode詳細

| モード | フラグ | 動作 |
|--------|--------|------|
| OPEN_OR_CREATE | O_CREAT | ファイルが存在すれば開く、なければ作成 |
| TRUNCATE | O_TRUNC \| O_CREAT | ファイルを0バイトに切り詰めて開く |
| APPEND | O_APPEND \| O_CREAT | 追記モードで開く（seekは効果なし） |
| MUST_CREATE | O_EXCL \| O_CREAT | ファイルが存在しない場合のみ作成、存在すればエラー |

### 計算ロジック

**パーミッション引数の判定**:
```
permissions引数を渡す = ($mode & OS\O_CREAT) != 0
```

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ENOENT | OS\ErrnoException | 親ディレクトリが存在しない | ディレクトリを作成する |
| EACCES | OS\ErrnoException | 書き込み権限がない | ファイル/ディレクトリのパーミッションを確認 |
| EISDIR | OS\ErrnoException | パスがディレクトリ | ファイルパスを指定する |
| EEXIST | OS\ErrnoException | MUST_CREATEでファイルが既に存在 | 別のWriteModeを使用 |
| EMFILE | OS\ErrnoException | プロセスのFD上限に達した | ファイルを適切にclose |
| EROFS | OS\ErrnoException | 読み取り専用ファイルシステム | 書き込み可能なパスを使用 |

### リトライ仕様

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

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

該当なし（ファイルシステムのアトミック性に依存）

## パフォーマンス要件

- ファイルオープンはOSのシステムコールに依存
- APPENDモードは複数プロセスからの同時追記に安全
- 大量のファイルを開く場合はFD上限に注意

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

- ファイルパスのバリデーション（パストラバーサル対策）は呼び出し元の責任
- デフォルトパーミッション0644は他ユーザーからの読み取りを許可
- センシティブなデータを書き込む場合は0600を推奨
- 既存ファイルを上書きする場合は意図した動作か確認

## 備考

- 非推奨の`open_write_only_nd`関数が存在するが、`open_write_only`を使用すること
- TRUNCATEモードは既存の内容を消去するので注意
- APPENDモードではseek()を呼び出しても書き込み位置は常にファイル末尾
- truncate()メソッドで任意の位置でファイルを切り詰め可能

---

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

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

### 推奨読解順序

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

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

**読解のコツ**: デフォルト引数とビット演算に注目。

**主要処理フロー**:
- **21行目**: `WriteMode $mode = WriteMode::OPEN_OR_CREATE` - デフォルトモード
- **22行目**: `int $create_file_permissions = 0644` - デフォルトパーミッション
- **24-26行目**: `OS\O_WRONLY | $mode as int` - フラグの結合
- **27行目**: `($mode & OS\O_CREAT)` - O_CREATフラグのチェック

#### Step 2: WriteModeを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | WriteMode.php | `src/file/WriteMode.php` | WriteMode列挙型（15-45行目） |

**主要なモード**:
- **23行目**: `OPEN_OR_CREATE = OS\O_CREAT` - 作成または開く
- **30行目**: `TRUNCATE = OS\O_TRUNC | OS\O_CREAT` - 切り詰めて開く
- **37行目**: `APPEND = OS\O_APPEND | OS\O_CREAT` - 追記モード
- **44行目**: `MUST_CREATE = OS\O_EXCL | OS\O_CREAT` - 新規作成のみ

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | CloseableWriteHandle.php | `src/file/_Private/CloseableWriteHandle.php` | 書き込みハンドル実装 |

**主要処理フロー**:
- **17-18行目**: `extends CloseableFileHandle implements File\CloseableWriteHandle`
- **19行目**: `use _IO\FileDescriptorWriteHandleTrait` - 書き込み機能
- **20行目**: `use TruncateTrait` - 切り詰め機能

#### Step 4: 書き込みインターフェースを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Handle.php | `src/file/Handle.php` | WriteHandleインターフェース（51-53行目） |

**主要なメソッド**:
- **52行目**: `truncate(?int $length = null): void` - ファイルの切り詰め

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

```
File\open_write_only($path, $mode, $permissions)
    |
    +-- フラグ計算: OS\O_WRONLY | $mode as int
    |
    +-- permissions判定: ($mode & OS\O_CREAT) ? $permissions : null
    |
    +-- OS\open($path, $flags, $permissions)
    |       |
    |       +-- FileDescriptor を返却
    |
    +-- new _File\CloseableWriteHandle($fd, $path)
            |
            +-- extends CloseableFileHandle
            +-- use _IO\FileDescriptorWriteHandleTrait
            |       |
            |       +-- writeAllowPartialSuccessAsync()
            |       +-- writeAllAsync()
            |
            +-- use TruncateTrait
                    |
                    +-- truncate($length)
```

### データフロー図

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

string $path
WriteMode $mode
int $permissions
    |
    v
┌─────────────────────────────────────────────────────────────────────┐
│ フラグ生成                                                          │
│   O_WRONLY | mode                                                   │
│   - OPEN_OR_CREATE: O_WRONLY | O_CREAT                             │
│   - TRUNCATE: O_WRONLY | O_TRUNC | O_CREAT                         │
│   - APPEND: O_WRONLY | O_APPEND | O_CREAT                          │
│   - MUST_CREATE: O_WRONLY | O_EXCL | O_CREAT                       │
└─────────────────────────────────────────────────────────────────────┘
    |
    v
┌─────────────────────────────────────────────────────────────────────┐
│ OS\open($path, $flags, $permissions)                                │
│   - システムコールでファイルを開く/作成                              │
│   - FileDescriptor を取得                                           │
└─────────────────────────────────────────────────────────────────────┘
    |
    v
┌─────────────────────────────────────────────────────────────────────┐
│ CloseableWriteHandle($fd, $path)                                    │
│   - 書き込み操作を提供                                               │
│     - writeAllowPartialSuccessAsync()                               │
│     - writeAllAsync()                                               │
│     - truncate()                                                    │
└─────────────────────────────────────────────────────────────────────┘
    |
    v
CloseableWriteHandle ──────────> ファイルへの書き込み
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| open.php | `src/file/open.php` | ソース | open_write_only関数の定義 |
| WriteMode.php | `src/file/WriteMode.php` | ソース | WriteMode列挙型の定義 |
| Handle.php | `src/file/Handle.php` | ソース | WriteHandleインターフェース |
| CloseableHandle.php | `src/file/CloseableHandle.php` | ソース | CloseableWriteHandleインターフェース |
| CloseableWriteHandle.php | `src/file/_Private/CloseableWriteHandle.php` | ソース | 書き込みハンドルの実装 |
| CloseableFileHandle.php | `src/file/_Private/CloseableFileHandle.php` | ソース | ファイルハンドルの基底実装 |
| TruncateTrait.php | `src/file/_Private/TruncateTrait.php` | ソース | 切り詰め機能のトレイト |
| FileTest.php | `tests/file/FileTest.php` | テスト | ファイル操作のテスト |
