# 機能設計書 20-ファイルディスクリプタ取得

## 概要

`uv_fileno()`によりハンドルに関連付けられたOSファイルディスクリプタを取得する機能の設計書である。

### 本機能の処理概要

**業務上の目的・背景**：libuvのハンドルは内部でOSのファイルディスクリプタ（Unix）やHANDLE（Windows）を保持している。アプリケーションがOS固有のAPIを直接呼び出す必要がある場合や、ファイルディスクリプタを外部ライブラリに渡す必要がある場合に、ハンドルから対応するFDを取得する手段が必要である。

**機能の利用シーン**：OS固有のソケットオプション設定、外部ライブラリとの統合、デバッグ目的でのFD確認、ファイルディスクリプタを直接操作する必要がある低レベル処理などに使用される。

**主要な処理内容**：
1. ハンドル型に応じてファイルディスクリプタの取得元を決定する
2. TCP/パイプ/TTY: `uv__stream_fd()`でストリームのFDを取得
3. UDP: `io_watcher.fd`からFDを取得
4. Poll: `io_watcher.fd`からFDを取得
5. クローズ中またはFDが-1の場合はUV_EBADFを返す

**関連システム・外部連携**：OSのファイルディスクリプタを返却するため、外部ライブラリやOS固有APIとの連携に使用される。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 7 | ハンドル基底 | 主機能 | uv_fileno()によるOSファイルディスクリプタ取得のAPI定義 |

## 機能種別

データ取得

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| handle | const uv_handle_t* | Yes | 対象のハンドル | NULLチェックなし |
| fd | uv_os_fd_t* | Yes | 取得したFDの格納先 | NULLチェックなし |

### 入力データソース

呼び出し元から渡されるハンドル構造体ポインタとFD格納先ポインタ。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | int | 成功時0、エラー時は負のエラーコード |
| *fd | uv_os_fd_t | ハンドルに関連付けられたOSファイルディスクリプタ |

### 出力先

戻り値として呼び出し元へ返却。`*fd`にファイルディスクリプタが書き込まれる。

## 処理フロー

### 処理シーケンス

```
1. uv_fileno()が呼び出される
2. ハンドル型によるswitch分岐
   ├─ UV_TCP / UV_NAMED_PIPE / UV_TTY → uv__stream_fd()
   ├─ UV_UDP → io_watcher.fd
   ├─ UV_POLL → io_watcher.fd
   └─ default → UV_EINVAL
3. クローズ中チェック: uv__is_closing(handle) → UV_EBADF
4. FDが-1の場合 → UV_EBADF
5. *fd = fd_out として格納
6. return 0
```

### フローチャート

```mermaid
flowchart TD
    A[uv_fileno 呼び出し] --> B{ハンドル型?}
    B -->|TCP/PIPE/TTY| C[uv__stream_fd でFD取得]
    B -->|UDP| D[io_watcher.fd でFD取得]
    B -->|POLL| E[io_watcher.fd でFD取得]
    B -->|その他| F[UV_EINVAL]
    C --> G{クローズ中 or FD == -1?}
    D --> G
    E --> G
    G -->|Yes| H[UV_EBADF]
    G -->|No| I[*fd = fd_out, return 0]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-20-01 | 対応ハンドル型 | TCP、パイプ、TTY、UDP、Pollのみ対応 | 常時 |
| BR-20-02 | クローズ中不可 | クローズ中のハンドルからはFDを取得できない（UV_EBADF） | CLOSINGフラグセット時 |
| BR-20-03 | 未初期化不可 | FDが-1（未初期化）の場合はUV_EBADFを返す | FD未設定時 |
| BR-20-04 | 読み取り専用 | FDは読み取り用途であり、外部から直接クローズすべきでない | 常時 |

### 計算ロジック

特になし。ハンドル内部のFDフィールドの取得のみ。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EINVAL | パラメータエラー | 非対応のハンドル型 | 対応するハンドル型を使用する |
| UV_EBADF | 不正なFD | クローズ中またはFDが-1 | ハンドルが有効な状態であることを確認 |

### リトライ仕様

リトライ不要。

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

該当なし。

## パフォーマンス要件

O(1)の定数時間。構造体フィールドの読み取りのみ。

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

返却されるFDはlibuvが内部で管理しているものであり、外部からclose()等で直接操作するとlibuvの動作が破壊される可能性がある。読み取り目的でのみ使用すべきである。

## 備考

- `uv_os_fd_t`はUnixでは`int`、Windowsでは`HANDLE`型として定義される
- 取得したFDを直接close()すると未定義動作となる
- 参照: include/uv.h L509

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | **L509**: uv_fileno()のAPI宣言。第2引数はuv_os_fd_t*型 |
| 1-2 | uv.h | `include/uv.h` | **L472-475**: UV_HANDLE_FIELDSのu.fdフィールド（汎用FD格納） |

**読解のコツ**: ストリーム型ハンドル（TCP/パイプ/TTY）は`uv__stream_fd()`マクロでFDにアクセスする。UDPとPollは`io_watcher.fd`で直接アクセスする。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | core.c (unix) | `src/unix/core.c` | **L812-839**: uv_fileno()のUnix実装 |

**主要処理フロー**:
1. **815-828行目**: switch文でハンドル型ごとにFDの取得元を決定
2. **816-820行目**: TCP/NAMED_PIPE/TTY → `uv__stream_fd((uv_stream_t*) handle)`
3. **822-823行目**: UDP → `((uv_udp_t *) handle)->io_watcher.fd`
4. **826-827行目**: POLL → `((uv_poll_t *) handle)->io_watcher.fd`
5. **830-831行目**: その他 → `return UV_EINVAL`
6. **834-835行目**: クローズ中またはfd_out == -1 → `return UV_EBADF`
7. **837-838行目**: `*fd = fd_out; return 0;`

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

```
uv_fileno(handle, fd)                [src/unix/core.c:812]
    │
    ├─ switch(handle->type)
    │   ├─ UV_TCP/UV_NAMED_PIPE/UV_TTY
    │   │   └─ uv__stream_fd()     [ストリームFD取得マクロ]
    │   ├─ UV_UDP
    │   │   └─ handle->io_watcher.fd
    │   └─ UV_POLL
    │       └─ handle->io_watcher.fd
    │
    ├─ uv__is_closing() チェック    [src/uv-common.h:277]
    │
    └─ *fd = fd_out
```

### データフロー図

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

const uv_handle_t* handle ──> 型判定 → FD取得 ──────────> *fd (uv_os_fd_t)
uv_os_fd_t* fd ──────────────> 状態チェック ──────────────> return 0 or error
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | 公開API宣言（L509） |
| core.c (unix) | `src/unix/core.c` | ソース | Unix実装（L812-839） |
| handle.c (win) | `src/win/handle.c` | ソース | Windows実装 |
| uv-common.h | `src/uv-common.h` | ヘッダ | uv__is_closingマクロ |
| internal.h | `src/unix/internal.h` | ヘッダ | uv__stream_fd()マクロ定義 |
