# 帳票設計書 26-ホスト名

## 概要

システムのホスト名を文字列バッファに出力する帳票（API出力）の設計書である。`uv_os_gethostname()`関数により、OSに設定されたホスト名を取得する。

### 本帳票の処理概要

本帳票は、システムに設定されたホスト名を指定バッファに出力する機能を提供する。Unix系では`gethostname()`、Windowsでは`GetHostNameW()`（Winsock API）を使用してホスト名を取得し、呼び出し側が提供するバッファに格納する。

**業務上の目的・背景**：ネットワーク通信、分散システムにおけるノード識別、ログ出力へのホスト情報付加、クラスタ管理、サービスディスカバリなど、多くの場面でシステムのホスト名の取得が必要となる。クロスプラットフォームなアプリケーションにおいて、OS固有のホスト名取得APIの差異を吸収し、バッファサイズ不足の検出も統一的に行うことが本関数の目的である。

**帳票の利用シーン**：アプリケーションログへのホスト名付加、分散システムでのノード識別子生成、ネットワークサービスの自己登録、ヘルスチェック応答へのホスト情報埋め込み、監視システムでのホスト識別などに利用される。

**主要な出力内容**：
1. ホスト名文字列（NULLターミネート）
2. ホスト名の文字数（sizeパラメータに返却）

**帳票の出力タイミング**：任意のタイミングで`uv_os_gethostname()`関数を呼び出すことにより出力される。同期関数であり、即座に結果が返却される。

**帳票の利用者**：libuvを利用するアプリケーション開発者、Node.jsランタイム（os.hostname()の内部実装）、ネットワークアプリケーション開発者、運用監視ツール開発者。

## 帳票種別

情報取得（ホスト名文字列出力）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | CLIまたはAPI呼び出し | N/A（C言語API） | `uv_os_gethostname()` 関数呼び出し |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | 文字列（char*バッファ） |
| 用紙サイズ | N/A |
| 向き | N/A |
| ファイル名 | N/A（呼び出し側バッファに書き込み） |
| 出力方法 | 引数バッファへの文字列書き込み |
| 文字コード | UTF-8 |

### 出力データ仕様

| 項目 | 型 | 説明 |
|-----|-----|------|
| buffer | char* | ホスト名が書き込まれるバッファ（呼び出し側で確保） |
| *size | size_t | 入力: バッファサイズ / 出力: ホスト名の文字数（NUL含まず） |
| 戻り値 | int | 0=成功、負値=エラーコード |

### バッファサイズ定数

| 定数名 | 定義 | 値 | 備考 |
|-------|------|-----|------|
| UV_MAXHOSTNAMESIZE | `include/uv.h` | MAXHOSTNAMELEN + 1（定義済みの場合）または256 | ホスト名の最大長を含むバッファサイズ |

## 帳票レイアウト

### レイアウト概要

本帳票は単一の文字列値として出力される。

```
┌─────────────────────────────────────┐
│  ホスト名文字列                       │
│  "myhost.example.com\0"             │
│  size = 19                          │
└─────────────────────────────────────┘
```

### 出力項目

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | ホスト名 | システムに設定されたホスト名 | gethostname() / GetHostNameW() | NULLターミネート文字列 |
| 2 | サイズ | ホスト名の文字数 | strlen(hostname) | size_t値 |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| buffer | ホスト名を格納するバッファ。NULL不可 | Yes |
| size | バッファサイズを持つsize_t変数へのポインタ。NULL不可、*size > 0 | Yes |

### ソート順

N/A（単一値出力）

### 改ページ条件

N/A

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

### 参照テーブル一覧

本帳票はデータベースを参照しない。OSのネットワーク設定からホスト名を取得する。

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| N/A | N/A | N/A |

### プラットフォーム別データ取得元

| プラットフォーム | ファイル | 取得方法 | 備考 |
|---------------|---------|---------|------|
| Unix系 | `src/unix/core.c` | gethostname() を内部バッファ（UV_MAXHOSTNAMESIZE）に取得後、呼び出し側バッファにコピー | バッファサイズ不足の検出あり |
| Windows | `src/win/util.c` | pGetHostNameW()（Winsock API）を使用 | UTF-16からUTF-8への変換が必要 |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| バッファサイズ検証 | strlen(hostname) >= *size の場合はENOBUFS | N/A | 十分なバッファが必要 |
| 出力サイズ | strlen(hostname) | N/A | NULLターミネータを含まない文字数 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[uv_os_gethostname 呼び出し] --> B{引数チェック}
    B -->|buffer==NULL or size==NULL or *size==0| C[UV_EINVAL を返却]
    B -->|OK| D{プラットフォーム判定}
    D -->|Unix| E[内部バッファに gethostname 呼び出し]
    E --> F{gethostname 成功?}
    F -->|No| G[UV__ERR errno を返却]
    F -->|Yes| H[strlen で長さ計算]
    H --> I{len >= *size?}
    I -->|Yes| J[*size = len + 1 を設定]
    J --> K[UV_ENOBUFS を返却]
    I -->|No| L[memcpy でバッファにコピー]
    L --> M[*size = len を設定]
    M --> N[0 を返却]
    D -->|Windows| O[uv__once_init Winsock初期化]
    O --> P{pGetHostNameW 利用可能?}
    P -->|No| Q[UV_ENOSYS を返却]
    P -->|Yes| R[pGetHostNameW で取得]
    R --> S{成功?}
    S -->|No| T[WSAGetLastError を変換して返却]
    S -->|Yes| U[uv__copy_utf16_to_utf8 で変換]
    U --> N
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| UV_EINVAL | buffer==NULL, size==NULL, または *size==0 の場合 | N/A | 有効なバッファとサイズを渡す |
| UV_ENOBUFS | バッファサイズがホスト名の長さに対して不足している場合 | N/A | *sizeに必要なサイズが返却されるので、そのサイズでバッファを再確保 |
| UV_ENOSYS | Windows で pGetHostNameW が利用できない場合 | N/A | Winsock の初期化状態を確認 |
| システムエラー | gethostname / GetHostNameW が失敗した場合 | UV__ERR(errno) / WSAGetLastError() | OS/ネットワーク設定を確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 1件（単一文字列） |
| 目標出力時間 | マイクロ秒オーダー（システムコール1回 + memcpy） |
| 同時出力数上限 | 制限なし（呼び出し側バッファを使用、スレッドセーフ） |

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

- ホスト名は一般にセンシティブな情報ではないが、内部ネットワーク構成の推測材料になりうる
- Unix実装では内部バッファ（UV_MAXHOSTNAMESIZE）を使用し、一部プラットフォームでのgethostnameによるバッファオーバーフローの問題を回避している
- Windows実装ではWinsockの初期化（uv__once_init）が前提条件となる

## 備考

- Unix実装では、一部プラットフォームでgethostname()がバッファ不足でも成功して文字列を切り詰める問題があるため、内部で十分なサイズのバッファ（UV_MAXHOSTNAMESIZE）を使用して取得し、実際の長さを呼び出し側バッファサイズと比較する設計となっている
- UV_MAXHOSTNAMESIZEは、MAXHOSTNAMELENが定義されている場合はMAXHOSTNAMELEN+1、そうでない場合は256
- バッファサイズが不足している場合、*sizeに必要なサイズ（len+1）が設定されるため、呼び出し側は再確保して再呼び出しが可能
- Windows実装ではpGetHostNameWがNULLの場合（Winsock未初期化時の異常）UV_ENOSYSを返す

---

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

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

### 推奨読解順序

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

uv_os_gethostname は構造体を使用せず、char バッファと size_t に直接書き込む。バッファサイズの上限定数を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | UV_MAXHOSTNAMESIZE の定義（行1375-1383）: MAXHOSTNAMELEN+1 または 256 |
| 1-2 | uv.h | `include/uv.h` | uv_os_gethostname() の宣言（行1386）: `int uv_os_gethostname(char* buffer, size_t* size)` |

**読解のコツ**: バッファサイズのin/outパターンに注意。入力時は確保済みサイズ、成功時は実際の文字数、ENOBUFS時は必要なサイズが *size に設定される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | core.c | `src/unix/core.c` | uv_os_gethostname() 関数（行1628-1655）: gethostname + バッファサイズ検証の完全実装 |

**主要処理フロー**:
1. **行1635**: 内部バッファ `char buf[UV_MAXHOSTNAMESIZE]` を宣言
2. **行1638-1639**: 引数の NULL チェックおよび *size == 0 チェック（UV_EINVAL）
3. **行1641-1642**: `gethostname(buf, sizeof(buf))` を呼び出し。失敗時は UV__ERR(errno)
4. **行1644**: バッファの最後をNULLターミネート（安全策）
5. **行1645**: `strlen(buf)` でホスト名の長さを計算
6. **行1647-1649**: len >= *size の場合、*size = len + 1 を設定して UV_ENOBUFS を返却
7. **行1652**: `memcpy(buffer, buf, len + 1)` で呼び出し側バッファにコピー（NUL含む）
8. **行1653**: `*size = len` で文字数を設定

#### Step 3: Windows実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | util.c | `src/win/util.c` | uv_os_gethostname() 関数（行1404-1419）: GetHostNameW + UTF-16→UTF-8 変換 |

**主要処理フロー（Windows）**:
1. **行1405**: 内部バッファ `WCHAR buf[UV_MAXHOSTNAMESIZE]` を宣言
2. **行1407-1408**: 引数の NULL チェックおよび *size == 0 チェック（UV_EINVAL）
3. **行1410**: `uv__once_init()` で Winsock を初期化
4. **行1412-1413**: `pGetHostNameW` が NULL の場合 UV_ENOSYS を返却
5. **行1415-1416**: `pGetHostNameW(buf, UV_MAXHOSTNAMESIZE)` でホスト名取得
6. **行1418**: `uv__copy_utf16_to_utf8(buf, -1, buffer, size)` で UTF-8 変換と結果コピー

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

```
uv_os_gethostname(char* buffer, size_t* size)  [src/unix/core.c:1628]
    |
    +-- gethostname(buf, sizeof(buf))       [libc]
    +-- strlen(buf)                         [libc]
    +-- memcpy(buffer, buf, len + 1)        [libc]

uv_os_gethostname(char* buffer, size_t* size)  [src/win/util.c:1404]
    |
    +-- uv__once_init()                     [src/win/util.c]
    +-- pGetHostNameW(buf, UV_MAXHOSTNAMESIZE)  [Winsock API]
    +-- uv__copy_utf16_to_utf8(buf, ...)    [src/win/util.c]
```

### データフロー図

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

char* buffer ───> OS ホスト名取得         ───> buffer = "hostname\0"
size_t* size      gethostname (Unix)           *size = strlen(hostname)
                  GetHostNameW (Windows)        戻り値: 0 または負値
                  + UTF-8 変換 (Windows)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | UV_MAXHOSTNAMESIZE 定義、uv_os_gethostname() API宣言 |
| core.c | `src/unix/core.c` | ソース | Unix向け uv_os_gethostname() 実装 |
| util.c | `src/win/util.c` | ソース | Windows向け uv_os_gethostname() 実装 |
| test-gethostname.c | `test/test-gethostname.c` | テスト | uv_os_gethostname のテスト |
