# 機能設計書 42-ファイル操作

## 概要

Julia Base ライブラリにおけるファイルの作成・削除・コピー・移動・リンク操作などのファイルシステム操作を提供する機能の設計書である。

### 本機能の処理概要

**業務上の目的・背景**：プログラムがファイルシステム上のファイルやディレクトリを操作する際には、OS 固有のシステムコールを適切に呼び出す必要がある。本機能は libuv および C ランタイムを介してクロスプラットフォームなファイル操作 API を Julia ユーザーに提供し、OS 間の差異を吸収する。

**機能の利用シーン**：データ処理のためのファイルのコピー・移動、不要ファイルの削除、シンボリックリンクやハードリンクの作成、ディレクトリの作成・削除、ファイルパーミッションの変更、ファイルのタッチ（タイムスタンプ更新）など、あらゆるファイル管理操作に使用される。

**主要な処理内容**：
1. `cp` によるファイル・ディレクトリのコピー（再帰コピー対応）
2. `mv` によるファイル・ディレクトリの移動（リネーム）
3. `rm` によるファイル・ディレクトリの削除（再帰削除対応）
4. `mkdir` / `mkpath` によるディレクトリ作成
5. `touch` によるファイルの作成またはタイムスタンプ更新
6. `symlink` / `hardlink` / `readlink` によるリンク操作
7. `chmod` によるパーミッション変更
8. `rename` によるファイルのリネーム（アトミック操作）
9. `sendfile` によるカーネルレベルの効率的ファイルコピー

**関連システム・外部連携**：libuv（`uv_fs_*` 系関数）、C ランタイム（`rename`, `sendfile` 等）、OS のファイルシステム API と直接連携する。

**権限による制御**：ファイル操作はすべて OS のファイルシステムパーミッションに従う。`chmod` で明示的にパーミッション変更が可能。`force=true` オプションで書き込み保護ファイルの強制削除が可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | CLI / REPL | 主画面 | ファイル操作関数の対話的実行 |

## 機能種別

ファイルシステム操作 / CRUD操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| src | AbstractString | Yes | 操作元のファイルパス | パスが存在すること（操作による） |
| dst | AbstractString | Yes/No | 操作先のファイルパス | 操作によっては不要 |
| force | Bool | No | 既存ファイルの強制上書き（デフォルト: false） | - |
| recursive | Bool | No | ディレクトリの再帰的操作（デフォルト: false） | - |
| follow_symlinks | Bool | No | シンボリックリンクの追従（デフォルト: true） | - |

### 入力データソース

ユーザーコードから文字列パスとオプションフラグとして直接渡される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| dst | String | cp/mv の結果のパス |
| path | String | mkdir/mkpath の結果のパス |
| - | Nothing | rm/touch/chmod の戻り値（なし） |

### 出力先

ファイルシステム上に実際のファイル・ディレクトリが作成・変更・削除される。

## 処理フロー

### 処理シーケンス

```
1. パスの検証
   └─ 入力パスの存在確認・型チェック
2. オプションの解釈
   └─ force, recursive, follow_symlinks 等のフラグ処理
3. ファイルシステム操作の実行
   └─ libuv / ccall 経由でシステムコールを発行
4. エラーハンドリング
   └─ SystemError / IOError の捕捉と適切なメッセージ生成
5. 結果の返却
   └─ 操作結果のパスまたは Nothing を返却
```

### フローチャート

```mermaid
flowchart TD
    A[ファイル操作要求] --> B{操作種別}
    B -->|cp| C{ディレクトリ?}
    C -->|Yes| D[再帰コピー]
    C -->|No| E[sendfile でコピー]
    B -->|mv| F[rename 試行]
    F --> G{同一FS?}
    G -->|Yes| H[アトミックリネーム]
    G -->|No| I[cp + rm]
    B -->|rm| J{ディレクトリ?}
    J -->|Yes| K{recursive?}
    K -->|Yes| L[再帰削除]
    K -->|No| M[エラー]
    J -->|No| N[unlink]
    B -->|mkdir| O[uv_fs_mkdir]
    B -->|touch| P[open + close / futimes]
    D --> Q[完了]
    E --> Q
    H --> Q
    I --> Q
    L --> Q
    N --> Q
    O --> Q
    P --> Q
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-42-01 | コピー先の存在チェック | force=false の場合、コピー先にファイルが存在するとエラー | cp 呼出時 |
| BR-42-02 | 再帰削除の安全ガード | recursive=false の場合、ディレクトリの rm はエラー | rm 呼出時 |
| BR-42-03 | mv のフォールバック | rename がファイルシステム跨ぎで失敗した場合、cp+rm にフォールバック | mv 呼出時 |
| BR-42-04 | mkpath の冪等性 | 既にディレクトリが存在する場合はエラーにならない | mkpath 呼出時 |
| BR-42-05 | symlink の follow_symlinks | follow_symlinks=false の場合、シンボリックリンク自体をコピー | cp 呼出時 |

### 計算ロジック

`sendfile` はカーネルレベルのゼロコピー機構を利用してファイルコピーを高速化する。OS ごとに異なるシステムコール（Linux: `sendfile(2)`, macOS: `fcopyfile`）を使い分ける。

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

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

該当なし。ファイルシステム上の操作のみ。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| IOError | SystemError | ファイルが存在しない（rm, cp の src） | パスの存在確認 |
| IOError | SystemError | パーミッション不足 | chmod で権限変更、または force=true |
| ArgumentError | ArgumentError | 不正な引数組み合わせ | ドキュメント参照 |
| IOError | SystemError | ディスク容量不足（cp, mv） | ディスク空き容量の確保 |

### リトライ仕様

ファイルシステム操作は一般にリトライ不要。ネットワークファイルシステムの場合はアプリケーション層でのリトライが推奨される。

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

`rename` はアトミック操作であり、成功するか何も変更しないかのいずれかである。`mv` は `rename` がファイルシステム跨ぎで失敗した場合に `cp` + `rm` にフォールバックするため、この場合はアトミックではない。

## パフォーマンス要件

- `sendfile` によるカーネルレベルコピーにより、大きなファイルのコピーが効率的に行われる
- `mkpath` は中間ディレクトリを一つずつ作成するため、深いパス階層では複数回のシステムコールが発生する

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

- `force=true` オプションは書き込み保護ファイルの削除を許可するため、慎重に使用する必要がある
- `symlink` は任意のパスへのリンクを作成できるため、パストラバーサル攻撃の経路となり得る
- `chmod` は適切な権限で実行する必要がある

## 備考

- Windows では `symlink` にディレクトリリンク用の特別なフラグ (`UV_FS_SYMLINK_JUNCTION`, `UV_FS_SYMLINK_DIR`) が存在する
- `cp` のパーミッションコピーは `follow_symlinks` フラグの影響を受ける
- `cptree` は内部的に使用されるディレクトリツリーコピー関数である

---

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

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

### 推奨読解順序

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

ファイル操作は主にパス文字列とファイルディスクリプタを扱う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | file.jl | `base/file.jl` | **1-30行目**: export 宣言から公開 API の一覧を把握する |
| 1-2 | stat.jl | `base/stat.jl` | **1-50行目**: StatStruct の定義。ファイル操作の前提となるファイル情報の構造体 |

**読解のコツ**: `ccall` による libuv 関数の呼び出しが多用される。`uv_fs_*` がファイルシステム操作の libuv API である。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | file.jl | `base/file.jl` | **32-80行目**: `mkdir` / `mkpath` の実装。libuv の `uv_fs_mkdir` を使用 |
| 2-2 | file.jl | `base/file.jl` | **82-130行目**: `rm` の実装。再帰削除・force オプションの処理 |

**主要処理フロー**:
1. **132-200行目**: `touch` - ファイルの作成またはタイムスタンプ更新
2. **202-280行目**: `cp` - ファイルコピー。`sendfile` を内部使用
3. **282-340行目**: `mv` - ファイル移動。`rename` + フォールバック
4. **342-400行目**: `symlink` / `hardlink` / `readlink` - リンク操作
5. **402-450行目**: `chmod` - パーミッション変更
6. **452-500行目**: `rename` - アトミックリネーム

#### Step 3: 内部ヘルパー関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | file.jl | `base/file.jl` | **sendfile 関数**: カーネルレベルファイルコピーの実装 |
| 3-2 | file.jl | `base/file.jl` | **cptree 関数**: ディレクトリツリーの再帰コピー |

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

```
cp(src, dst)
    ├─ isdir(src) 判定
    │      ├─ [dir] cptree(src, dst)
    │      │          ├─ mkdir(dst)
    │      │          └─ cp(子要素...) [再帰]
    │      └─ [file] sendfile(src, dst)
    │                  └─ ccall(:uv_fs_sendfile / :sendfile)
    └─ chmod(dst) ... パーミッションコピー

mv(src, dst)
    ├─ rename(src, dst)
    │      └─ ccall(:jl_fs_rename)
    └─ [fallback] cp(src, dst) + rm(src)

rm(path)
    ├─ isdir(path) 判定
    │      ├─ [dir+recursive] rm.(readdir(path)) [再帰]
    │      │                  └─ ccall(:uv_fs_rmdir)
    │      └─ [file] unlink(path)
    │                └─ ccall(:jl_fs_unlink)
    └─ [force] chmod + retry

mkdir(path) ─── ccall(:uv_fs_mkdir)
mkpath(path) ── mkdir.(中間ディレクトリ) [再帰]
touch(path)  ── open + close / futimes
```

### データフロー図

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

ソースパス ──────▶ cp ─▶ sendfile/cptree      ──────▶ コピー先ファイル
ソースパス ──────▶ mv ─▶ rename/cp+rm         ──────▶ 移動先ファイル
パス       ──────▶ rm ─▶ unlink/rmdir         ──────▶ ファイル削除
パス       ──────▶ mkdir ─▶ uv_fs_mkdir       ──────▶ ディレクトリ作成
パス       ──────▶ touch ─▶ open+futimes      ──────▶ ファイル作成/更新
パス+mode  ──────▶ chmod ─▶ uv_fs_chmod       ──────▶ 権限変更
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| file.jl | `base/file.jl` | ソース | ファイル操作の主要関数を定義 |
| path.jl | `base/path.jl` | ソース | パス操作関数（ファイル操作の前処理） |
| stat.jl | `base/stat.jl` | ソース | ファイル情報取得（isdir/isfile 等の判定） |
| iostream.jl | `base/iostream.jl` | ソース | IOStream によるファイル入出力 |
| filesystem.jl | `base/filesystem.jl` | ソース | 低レベルファイルシステム操作 |
