# 機能設計書 83-アーカイブ・圧縮

## 概要

本ドキュメントは、FreeBSDにおけるアーカイブ・圧縮コマンド群（pax、cpio、bzip2、compress）の機能設計を記述する。これらはファイルのアーカイブ作成・圧縮・展開を行うユーザ空間コマンドであり、FreeBSDベースシステムに含まれるPOSIX準拠ユーティリティである。

### 本機能の処理概要

**業務上の目的・背景**：アーカイブ・圧縮機能はバックアップ、ファイル転送、ディストリビューション配布において不可欠なツールである。pax/cpioはPOSIX標準のアーカイブフォーマットを提供し、bzip2/compressはデータ圧縮・伸長を行う。tarコマンドの基盤としても使用され、FreeBSDのリリースビルドやパッケージングにも関わる。

**機能の利用シーン**：システムバックアップ（pax/cpio）、ファイルのネットワーク転送前の圧縮（bzip2/compress）、ソフトウェアパッケージの展開、インストーラでの配布ファイル処理。

**主要な処理内容**：
1. pax: POSIX標準のアーカイブユーティリティ。読み取り(list/extract)、書き込み(create)、コピー(directory copy)の3モードをサポート。tar/cpioフォーマット互換
2. cpio: paxと同一バイナリ。cpio形式アーカイブの読み書き。ファイルリストを標準入力から受け取るパイプライン指向設計
3. bzip2: Burrows-Wheeler変換によるブロックソート圧縮。高圧縮率のデータ圧縮・伸長
4. compress: 従来のLZW（Lempel-Ziv-Welch）圧縮。.Zファイル形式のレガシーサポート

**関連システム・外部連携**：ファイルシステム（ファイルメタデータ保存・復元）、libbz2（bzip2圧縮ライブラリ）。

**権限による制御**：一般ユーザで実行可能。アーカイブ展開時のファイル所有権復元にはroot権限が必要。

## 関連画面

該当なし（CLIコマンドのため画面は存在しない）

## 機能種別

アーカイブ作成・展開 / データ圧縮・伸長

## 入力仕様

### 入力パラメータ

#### pax

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -r | flag | No | 読み取り（アーカイブ展開）モード | -wと排他 |
| -w | flag | No | 書き込み（アーカイブ作成）モード | -rと排他 |
| -rw | flag | No | コピーモード | - |
| -f archive | string | No | アーカイブファイル名 | ファイルアクセス可能 |
| -x format | string | No | アーカイブ形式（cpio/ustar/pax等） | 有効なフォーマット名 |
| -v | flag | No | 詳細出力 | - |
| -p string | string | No | ファイル属性保存オプション | 有効な属性文字列 |
| pattern | string | No | ファイルマッチパターン | - |

#### compress

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -c | flag | No | 標準出力に圧縮結果を出力 | - |
| -d | flag | No | 伸長モード | - |
| -f | flag | No | 既存ファイル上書き | - |
| -v | flag | No | 圧縮率を表示 | - |
| -b bits | integer | No | 最大ビット数（9-16） | 9以上16以下 |
| file | string | No | 圧縮/伸長対象ファイル | 存在すること |

### 入力データソース

コマンドライン引数で指定されたファイル、標準入力からのファイルリスト（cpio）、アーカイブファイル。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| アーカイブファイル | binary | pax/cpio形式のアーカイブ |
| 展開ファイル | file | アーカイブから展開されたファイル群 |
| 圧縮ファイル | binary | .bz2/.Z形式の圧縮データ |
| 伸長ファイル | file | 圧縮ファイルから復元されたデータ |

### 出力先

アーカイブファイル、標準出力（-cオプション時）、またはファイルシステム上の展開先ディレクトリ。

## 処理フロー

### 処理シーケンス（pax）

```
1. コマンドライン引数解析
   └─ options()でオプション解析、動作モード決定（act変数: LIST/EXTRACT/ARCHIVE/COPY）
2. 初期化
   └─ gen_init()で作業ディレクトリ・シグナルハンドラ設定
3. モード別処理
   ├─ LIST: アーカイブ内容一覧表示
   ├─ EXTRACT: アーカイブからファイル展開
   ├─ ARCHIVE: ファイルをアーカイブに書き込み
   └─ COPY: ディレクトリ間ファイルコピー
4. アーカイブI/O
   └─ ar_io.c: アーカイブファイルの読み書き
5. ファイル操作
   └─ file_subs.c: ファイル作成・属性設定・所有権復元
6. 終了処理
   └─ リソース解放、終了コード設定
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[オプション解析]
    B --> C{動作モード}
    C -->|LIST/EXTRACT| D[アーカイブ読み取り]
    C -->|ARCHIVE| E[アーカイブ書き込み]
    C -->|COPY| F[ディレクトリコピー]
    D --> G[ar_io: アーカイブI/O]
    E --> H[ftree: ファイルツリー走査]
    F --> I[file_subs: ファイル操作]
    G --> J[ヘッダ解析・ファイル展開]
    H --> K[ヘッダ作成・データ書込]
    I --> L[ファイルコピー・属性保存]
    J --> M[終了]
    K --> M
    L --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-83-01 | デフォルト動作 | paxはオプションなしでLISTモード（アーカイブ内容一覧） | act=DEFOP時 |
| BR-83-02 | アーカイブ形式互換 | paxはtar/cpio/ustar/pax形式の読み書きに対応 | -xオプション指定時 |
| BR-83-03 | 属性保存 | -pオプションでアクセス時間・パーミッション・所有権の保存を制御 | アーカイブ展開時 |
| BR-83-04 | compress上限 | LZW圧縮ビット数のデフォルトは16ビット | compress実行時 |
| BR-83-05 | 呼出名切替 | argv[0]がcpioの場合cpioモードで動作 | paxバイナリ起動時 |

### 計算ロジック

compress: LZW圧縮アルゴリズムにより最大16ビットの辞書サイズ（65536エントリ）で文字列置換を行う。bzip2: ブロックソート（Burrows-Wheeler変換）+ ムーブトゥフロント変換 + ハフマン符号化の3段階圧縮。

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | アーカイブ読取エラー | 破損アーカイブの読み取り | エラーメッセージ出力、処理続行または中止 |
| 1 | ディスクフル | 展開先のディスク容量不足 | エラーメッセージ出力 |
| 1 | 権限エラー | ファイル所有権復元失敗（非root） | 警告出力、処理続行 |
| 1 | フォーマットエラー | 不正なアーカイブ形式 | フォーマット判定失敗メッセージ |

### リトライ仕様

リトライは行わない。

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

アーカイブ展開は個別ファイル単位で処理される。途中エラー時は展開済みファイルはそのまま残る（ロールバックなし）。

## パフォーマンス要件

- paxはバッファリングI/O（buf_subs.c）によりアーカイブの読み書きを効率化
- bzip2はブロックサイズ設定（-1〜-9）によりメモリ使用量と圧縮率のトレードオフを制御可能

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

- アーカイブ展開時のパストラバーサル攻撃に対する保護（../を含むパスの検証）
- シンボリックリンクを含むアーカイブの安全な処理
- ファイルパーミッションの適切な復元

## 備考

- paxとcpioは同一バイナリ（pax.c内でargv[0]により動作切替）
- FreeBSDのbzip2はcontrib/bzip2からの取り込み。usr.bin/bzip2/MakefileでビルドのみMを管理
- tarコマンドはlibarchiveベースの別実装（bsdtarとして提供）

---

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

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

### 推奨読解順序

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

paxの内部データ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | extern.h | `bin/pax/extern.h` | 外部関数宣言とモジュール間インタフェース |
| 1-2 | pax.h | `bin/pax/pax.h` | アーカイブフォーマット定数、FSUB構造体（フォーマットサブシステム） |
| 1-3 | cpio.h | `bin/pax/cpio.h` | cpioヘッダ構造体定義 |
| 1-4 | options.h | `bin/pax/options.h` | オプション定義 |

**読解のコツ**: `FSUB`構造体がアーカイブフォーマットの抽象化層。各フォーマット（tar/cpio/ustar）はFSUBの関数ポインタで実装される。`act`変数（60行目）がLIST/EXTRACT/ARCHIVE/COPYの動作モードを決定する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | pax.c | `bin/pax/pax.c` | main()関数。グローバルフラグ宣言、gen_init()呼出、モード別処理分岐 |

**主要処理フロー**:
1. **60行目**: act=DEFOPのデフォルト動作モード
2. **61行目**: frmt=NULLの初期フォーマット（自動検出）
3. **62-79行目**: コマンドラインフラグ変数群（cflag, dflag, iflag, kflag等）
4. **80行目**: patime=1でデフォルトアクセス時間保存

#### Step 3: アーカイブI/O層

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ar_io.c | `bin/pax/ar_io.c` | アーカイブファイルのオープン・読み書き・クローズ |
| 3-2 | ar_subs.c | `bin/pax/ar_subs.c` | アーカイブサブルーチン（リスト/展開/書込の中核処理） |
| 3-3 | buf_subs.c | `bin/pax/buf_subs.c` | バッファリングI/O |

#### Step 4: ファイルツリーとパターンマッチ

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ftree.c | `bin/pax/ftree.c` | ファイルツリー走査 |
| 4-2 | pat_rep.c | `bin/pax/pat_rep.c` | パターンマッチと置換処理 |
| 4-3 | file_subs.c | `bin/pax/file_subs.c` | ファイル作成・属性設定 |

#### Step 5: compress実装

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | compress.c | `usr.bin/compress/compress.c` | main()関数。圧縮/伸長モード判定、ファイル処理 |
| 5-2 | zopen.c | `usr.bin/compress/zopen.c` | LZW圧縮エンジン（zopen/zread/zwrite） |

**主要処理フロー**:
- **47-53行目（compress.c）**: compress/decompress/permission/setfile関数宣言
- **55行目**: eval/force/verbose グローバル変数
- **60行目**: COMPRESS/DECOMPRESSモード判定enum

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

```
pax main()
    |
    +-- options()               # オプション解析・モード決定
    +-- gen_init()              # 初期化
    |
    +-- [LIST/EXTRACT モード]
    |       +-- ar_io: アーカイブオープン
    |       +-- ar_subs: ヘッダ読取・ファイル展開
    |       +-- file_subs: ファイル作成・属性復元
    |
    +-- [ARCHIVE モード]
    |       +-- ftree: ファイルツリー走査
    |       +-- ar_subs: ヘッダ作成・データ書込
    |       +-- ar_io: アーカイブ書込
    |
    +-- [COPY モード]
            +-- ftree: ソースファイルツリー走査
            +-- file_subs: ファイルコピー・属性保存

compress main()
    |
    +-- モード判定（argv[0]で compress/uncompress 切替）
    +-- compress(): zopen() -> ファイル圧縮
    +-- decompress(): zopen() -> ファイル伸長
    +-- setfile(): ファイル属性復元
```

### データフロー図

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

ファイルツリー ──> pax ARCHIVE: ar_subs ──> アーカイブファイル
                   ftree走査 -> ヘッダ生成 -> データ書込

アーカイブ ──> pax EXTRACT: ar_subs ──> 展開ファイル群
               ヘッダ解析 -> ファイル展開 -> 属性復元

ファイル ──> compress: zopen(LZW) ──> .Zファイル
ファイル ──> bzip2: BWT+MTF+Huffman ──> .bz2ファイル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| pax.c | `bin/pax/pax.c` | ソース | paxメインプログラム |
| pax.h | `bin/pax/pax.h` | ヘッダ | pax定数・フォーマット定義 |
| extern.h | `bin/pax/extern.h` | ヘッダ | 外部関数宣言 |
| ar_io.c | `bin/pax/ar_io.c` | ソース | アーカイブI/O |
| ar_subs.c | `bin/pax/ar_subs.c` | ソース | アーカイブ操作サブルーチン |
| buf_subs.c | `bin/pax/buf_subs.c` | ソース | バッファリングI/O |
| cpio.c | `bin/pax/cpio.c` | ソース | cpioフォーマット処理 |
| cpio.h | `bin/pax/cpio.h` | ヘッダ | cpioヘッダ定義 |
| file_subs.c | `bin/pax/file_subs.c` | ソース | ファイル操作（作成・属性設定） |
| ftree.c | `bin/pax/ftree.c` | ソース | ファイルツリー走査 |
| gen_subs.c | `bin/pax/gen_subs.c` | ソース | 汎用サブルーチン |
| getoldopt.c | `bin/pax/getoldopt.c` | ソース | 旧式オプション解析 |
| options.c | `bin/pax/options.c` | ソース | オプション解析 |
| pat_rep.c | `bin/pax/pat_rep.c` | ソース | パターンマッチ・置換 |
| cache.c | `bin/pax/cache.c` | ソース | UID/GIDキャッシュ |
| compress.c | `usr.bin/compress/compress.c` | ソース | compressコマンドメイン |
| zopen.c | `usr.bin/compress/zopen.c` | ソース | LZW圧縮エンジン |
| zopen.h | `usr.bin/compress/zopen.h` | ヘッダ | zopen関数宣言 |
