# 機能設計書 54-os（ファイルシステム操作）

## 概要

本ドキュメントは、Nim標準ライブラリのOS基本機能モジュール（os.nim）について、その設計と仕様を詳細に記載した機能設計書である。

### 本機能の処理概要

osモジュールは、環境変数の取得、ディレクトリ操作、シェルコマンドの実行など、基本的なオペレーティングシステム機能を提供する。複数のサブモジュール（ospaths2, osfiles, osdirs, ossymlinks, osappdirs, cmdline, envvars, oserrors）を統合して再エクスポートする。

**業務上の目的・背景**：アプリケーション開発において、ファイルシステム操作、パス操作、環境変数アクセス、シェルコマンド実行などのOS機能へのアクセスは不可欠である。本モジュールは、Windows、POSIX（Linux, macOS等）、その他のプラットフォームで一貫したAPIを提供し、クロスプラットフォーム開発を支援する。

**機能の利用シーン**：
- ファイルパスの結合、分割、正規化
- ファイル/ディレクトリの存在確認、作成、削除、移動
- シンボリックリンクの作成と操作
- 環境変数の読み書き
- シェルコマンドの実行
- アプリケーションディレクトリ（ホーム、設定、一時ディレクトリ）の取得
- コマンドライン引数の取得

**主要な処理内容**：
1. パス操作（splitPath, parentDir, splitFile, changeFileExt, expandTilde等）
2. ファイル操作（copyFile, moveFile, removeFile等）
3. ディレクトリ操作（createDir, removeDir, walkDir等）
4. シンボリックリンク操作（createSymlink, expandSymlink等）
5. 環境変数操作（getEnv, putEnv, existsEnv, delEnv等）
6. シェルコマンド実行（execShellCmd, quoteShell等）
7. アプリディレクトリ取得（getHomeDir, getConfigDir, getTempDir, getCurrentDir等）
8. コマンドライン引数取得（paramCount, paramStr, commandLineParams等）

**関連システム・外部連携**：
- Windows: winlean, Windows API
- POSIX: posix, POSIX API（unistd.h, dirent.h等）
- 各プラットフォーム固有のシステムコール

**権限による制御**：ファイルシステム操作には適切なファイル/ディレクトリ権限が必要。環境変数操作はプロセス内で有効。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本モジュールはライブラリ機能であり、直接の画面関連なし |

## 機能種別

CRUD操作 / システム連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|-----------------|
| path | string | Yes | ファイルまたはディレクトリのパス | 有効なパス文字列 |
| source | string | Yes | コピー/移動元のパス | 存在するパス |
| dest | string | Yes | コピー/移動先のパス | 有効なパス文字列 |
| key | string | Yes | 環境変数名 | 空でない文字列 |
| value | string | Yes | 環境変数の値 | 任意の文字列 |
| command | string | Yes | 実行するシェルコマンド | 有効なシェルコマンド |

### 入力データソース

- プログラムから直接渡されるパス文字列
- オペレーティングシステムの環境変数
- コマンドライン引数

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| パス | string | 操作結果のパス文字列 |
| 存在フラグ | bool | ファイル/ディレクトリの存在確認結果 |
| 環境変数値 | string | 取得した環境変数の値 |
| 終了コード | int | シェルコマンドの終了コード |
| ファイル情報 | FileInfo | ファイルの詳細情報 |
| ディレクトリ内容 | iterator | ディレクトリ内のエントリ |

### 出力先

呼び出し元への戻り値、ファイルシステムへの書き込み

## 処理フロー

### 処理シーケンス

```
1. パス操作
   └─ splitPath: パスをheadとtailに分割
   └─ parentDir: 親ディレクトリを取得
   └─ splitFile: ディレクトリ、ファイル名、拡張子に分割
   └─ changeFileExt: 拡張子を変更
   └─ expandTilde: ~をホームディレクトリに展開

2. ファイル操作
   └─ copyFile: ファイルをコピー
   └─ moveFile: ファイルを移動
   └─ removeFile: ファイルを削除
   └─ fileExists: ファイル存在確認

3. ディレクトリ操作
   └─ createDir: ディレクトリを作成
   └─ removeDir: ディレクトリを削除
   └─ dirExists: ディレクトリ存在確認
   └─ walkDir: ディレクトリ内を走査

4. 環境変数操作
   └─ getEnv: 環境変数を取得
   └─ putEnv: 環境変数を設定
   └─ existsEnv: 環境変数の存在確認
   └─ delEnv: 環境変数を削除

5. シェルコマンド実行
   └─ execShellCmd: シェルでコマンドを実行
   └─ quoteShell: シェル用にクォート
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{操作種別}
    B -->|パス操作| C[文字列処理]
    B -->|ファイル操作| D[ファイルシステムAPI呼び出し]
    B -->|ディレクトリ操作| E[ディレクトリAPI呼び出し]
    B -->|環境変数| F[環境変数API呼び出し]
    B -->|シェルコマンド| G[プロセス生成・実行]
    C --> H{Windows?}
    D --> H
    E --> H
    F --> H
    G --> H
    H -->|Yes| I[Windows API]
    H -->|No| J[POSIX API]
    I --> K[結果返却]
    J --> K
    K --> L[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | クロスプラットフォーム | Windows/POSIX両方で一貫したAPIを提供 | 常に適用 |
| BR-002 | パス区切り文字 | Windowsでは`\`、POSIXでは`/`を使用 | パス操作時 |
| BR-003 | 無効ファイル名 | invalidFilenameChars, invalidFilenames定数で無効文字/名前を定義 | ファイル作成時 |
| BR-004 | チルダ展開 | `~`をホームディレクトリに展開（Windowsでもサポート） | expandTilde使用時 |
| BR-005 | NimScript/JS制限 | 一部のプロシージャはNimScript/JSバックエンドで使用不可 | noWeirdTarget, noNimJsプラグマ |

### 計算ロジック

**パス分割（splitPath）**:
```nim
(head: "/path/to/my", tail: "file.nim")
```

**ファイル分割（splitFile）**:
```nim
(dir: "/path/to/my", name: "file", ext: ".nim")
```

**シェルクォート（quoteShellPosix）**:
```nim
const safeUnixChars = {'%', '+', '-', '.', '/', '_', ':', '=', '@', '0'..'9', 'A'..'Z', 'a'..'z'}
# 安全な文字のみならそのまま、それ以外はシングルクォートで囲む
```

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

### 操作別データベース影響一覧

本モジュールはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| OSError | 操作失敗 | ファイル/ディレクトリ操作の失敗 | エラーメッセージを確認し権限等をチェック |
| IOError | 入出力エラー | ファイル読み書きの失敗 | ファイルの存在と権限を確認 |
| - | ターゲット制限 | NimScript/JSでの未サポート操作 | サポートされるターゲットで実行 |

### リトライ仕様

- ファイル操作の一部はロック競合時にリトライが有効な場合がある
- 一般的にはアプリケーション側でリトライロジックを実装

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

ファイルシステム操作はアトミックではない。重要な操作では適切なバックアップ/ロールバック戦略を検討。

## パフォーマンス要件

- パス操作: O(n)（nはパス長）
- ファイル操作: ファイルシステムとファイルサイズに依存
- ディレクトリ走査: ディレクトリ内のエントリ数に依存

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

- シェルコマンド実行時はインジェクション攻撃に注意
- quoteShell/quoteShellCommand を使用して引数をエスケープ
- ファイルパスの検証（パストラバーサル攻撃の防止）
- 環境変数に機密情報を保存する場合は注意

## 備考

- 本モジュールは複数のサブモジュールを統合して再エクスポートする
- paths/filesモジュールは高レベルのファイル操作を提供
- osproc モジュールはより詳細なプロセス制御を提供

---

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

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

### 推奨読解順序

#### Step 1: モジュール構造を理解する

osモジュールは複数のサブモジュールを統合している。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | os.nim | `lib/pure/os.nim` | インポートとエクスポートの構造（32-108行目） |

**読解のコツ**: osモジュールは「ファサード」パターンを使用し、複数の専門モジュールを1つのAPIとして提供している。

#### Step 2: パス操作を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ospaths2.nim | `lib/std/private/ospaths2.nim` | splitPath, parentDir, splitFile等 |
| 2-2 | os.nim | `lib/pure/os.nim` | expandTilde（111-138行目） |

**主要処理フロー**:
- **130-138行目**: expandTildeの実装 - `~`で始まるパスをホームディレクトリに展開

#### Step 3: シェルクォートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | os.nim | `lib/pure/os.nim` | quoteShellWindows（140-170行目）、quoteShellPosix（173-182行目） |

**主要処理フロー**:
- **140行目**: quoteShellWindowsはPythonのsubprocess.list2cmdlineに基づく
- **175-176行目**: safeUnixCharsで安全な文字セットを定義

#### Step 4: 定数定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | os.nim | `lib/pure/os.nim` | invalidFilenameChars, invalidFilenames（64-75行目） |

#### Step 5: プラットフォーム分岐を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | os.nim | `lib/pure/os.nim` | weirdTarget, noWeirdTarget, noNimJs（61, 87-98行目） |

**読解のコツ**: NimScript/JSバックエンドでは一部の機能が制限される。`noWeirdTarget`プラグマはこれらのターゲットでエラーを生成。

#### Step 6: サブモジュールを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | osfiles.nim | `lib/std/private/osfiles.nim` | ファイル操作（copyFile, moveFile等） |
| 6-2 | osdirs.nim | `lib/std/private/osdirs.nim` | ディレクトリ操作（createDir, removeDir等） |
| 6-3 | ossymlinks.nim | `lib/std/private/ossymlinks.nim` | シンボリックリンク操作 |
| 6-4 | osappdirs.nim | `lib/std/private/osappdirs.nim` | アプリディレクトリ（getHomeDir等） |
| 6-5 | envvars.nim | `lib/std/envvars.nim` | 環境変数操作 |
| 6-6 | cmdline.nim | `lib/std/cmdline.nim` | コマンドライン引数 |

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

```
os.nim（ファサード）
    │
    ├─ ospaths2 (re-export)
    │      ├─ splitPath(path) → (head, tail)
    │      ├─ parentDir(path) → string
    │      ├─ splitFile(path) → (dir, name, ext)
    │      └─ changeFileExt(path, ext) → string
    │
    ├─ osfiles (re-export) [supportedSystem only]
    │      ├─ copyFile(source, dest)
    │      ├─ moveFile(source, dest)
    │      ├─ removeFile(path)
    │      └─ fileExists(path) → bool
    │
    ├─ osdirs (re-export) [supportedSystem only]
    │      ├─ createDir(path)
    │      ├─ removeDir(path)
    │      ├─ dirExists(path) → bool
    │      └─ walkDir(path) → iterator
    │
    ├─ ossymlinks (re-export) [supportedSystem only]
    │      ├─ createSymlink(src, dest)
    │      └─ expandSymlink(path) → string
    │
    ├─ osappdirs (re-export)
    │      ├─ getHomeDir() → string
    │      ├─ getConfigDir() → string
    │      └─ getTempDir() → string
    │
    ├─ envvars (re-export)
    │      ├─ getEnv(key, default) → string
    │      ├─ putEnv(key, value)
    │      ├─ existsEnv(key) → bool
    │      └─ delEnv(key)
    │
    ├─ cmdline (re-export)
    │      ├─ paramCount() → int
    │      ├─ paramStr(i) → string
    │      └─ commandLineParams() → seq[string]
    │
    └─ os.nim 独自
           ├─ expandTilde(path) → string
           ├─ quoteShellWindows(s) → string
           ├─ quoteShellPosix(s) → string
           ├─ quoteShell(s) → string
           └─ quoteShellCommand(args) → string
```

### データフロー図

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

パス文字列 ───────▶ splitPath() ─────────────▶ (head, tail)
パス文字列 ───────▶ parentDir() ─────────────▶ 親ディレクトリ
パス文字列 ───────▶ expandTilde() ───────────▶ 展開済みパス

source, dest ─────▶ copyFile() ──────────────▶ ファイルシステム更新
source, dest ─────▶ moveFile() ──────────────▶ ファイルシステム更新
path ─────────────▶ removeFile() ────────────▶ ファイル削除

path ─────────────▶ createDir() ─────────────▶ ディレクトリ作成
path ─────────────▶ walkDir() ───────────────▶ iterator[PathComponent]

key ──────────────▶ getEnv() ────────────────▶ 環境変数値
key, value ───────▶ putEnv() ────────────────▶ 環境変数設定

command ──────────▶ execShellCmd() ──────────▶ 終了コード
args ─────────────▶ quoteShellCommand() ─────▶ クォート済みコマンド
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| os.nim | `lib/pure/os.nim` | ソース | OSファシリティの統合モジュール |
| ospaths2.nim | `lib/std/private/ospaths2.nim` | ソース | パス操作 |
| osfiles.nim | `lib/std/private/osfiles.nim` | ソース | ファイル操作 |
| osdirs.nim | `lib/std/private/osdirs.nim` | ソース | ディレクトリ操作 |
| ossymlinks.nim | `lib/std/private/ossymlinks.nim` | ソース | シンボリックリンク操作 |
| osappdirs.nim | `lib/std/private/osappdirs.nim` | ソース | アプリディレクトリ取得 |
| envvars.nim | `lib/std/envvars.nim` | ソース | 環境変数操作 |
| cmdline.nim | `lib/std/cmdline.nim` | ソース | コマンドライン引数 |
| oserrors.nim | `lib/std/oserrors.nim` | ソース | OSエラー処理 |
| osseps.nim | `lib/std/private/osseps.nim` | ソース | パス区切り文字定義 |
| winlean.nim | `lib/std/winlean.nim` | ソース | Windows API |
| posix.nim | `lib/std/posix.nim` | ソース | POSIX API |
