# 機能設計書 92-libarchive

## 概要

本ドキュメントは、FreeBSDのlibarchiveライブラリの機能設計を記述する。libarchiveはtar、zip、cpio、ISO 9660、7-Zip等の多数のアーカイブ形式の読み書きを提供する汎用アーカイブ操作ライブラリである。

### 本機能の処理概要

libarchiveは、アーカイブファイルの作成・展開・読み取りを行うためのCライブラリである。FreeBSDのtarコマンド、cpioコマンド、bsdinstallでの配布ファイル展開など、システムの基盤コンポーネントとして広く利用されている。ストリーミングAPIを採用しており、大容量アーカイブの処理にも対応する。

**業務上の目的・背景**：FreeBSDシステムにおいて、パッケージの圧縮・展開、バックアップの作成、配布ファイルの展開など、多様なアーカイブ形式を統一的に処理する必要がある。libarchiveはこれらの要求を満たすマルチフォーマット対応のアーカイブライブラリとして設計されている。

**機能の利用シーン**：bsdinstallでの配布ファイル（tar.xz）の展開（画面No.20）、tarコマンドによるアーカイブ作成・展開、pkgパッケージマネージャでのパッケージ処理、cpioによるアーカイブ操作などで使用される。

**主要な処理内容**：
1. アーカイブの読み込み（archive_read系API）：ヘッダ解析、エントリ列挙、データ展開
2. アーカイブの書き込み（archive_write系API）：ヘッダ作成、データ圧縮、アーカイブ構築
3. ディスクへの展開（archive_write_disk系API）：パーミッション・所有者・タイムスタンプの復元
4. ディスクからの読み取り（archive_read_disk系API）：ファイルシステムのトラバーサル
5. 圧縮・解凍（gzip, bzip2, xz, lz4, zstd等の多数の圧縮形式対応）
6. アーカイブエントリのメタデータ操作（パーミッション、ACL、拡張属性等）
7. フォーマット自動検出

**関連システム・外部連携**：zlib（gzip圧縮）、liblzma（xz圧縮）、libbz2（bzip2圧縮）、libzstd（zstd圧縮）、OpenSSL（暗号化アーカイブ）

**権限による制御**：ディスクへの展開時にはファイルの所有者・パーミッション復元にroot権限が必要な場合がある。ARCHIVE_EXTRACT_OWNERフラグで制御。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 20 | 配布ファイル展開画面 | 主機能 | libarchiveを使用した配布ファイル（tar.xz）の展開・進捗表示 |

## 機能種別

データ連携（アーカイブ操作ライブラリ）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| struct archive * | struct archive * | Yes | アーカイブハンドル（archive_read_new/archive_write_new等で作成） | NULLチェック、マジック値検証 |
| struct archive_entry * | struct archive_entry * | Yes（エントリ操作時） | アーカイブエントリのメタデータ | NULLチェック |
| ファイルパス/ファイルデスクリプタ | const char * / int | Yes | 読み書き対象のファイル | 存在チェック、アクセス権チェック |
| ブロックサイズ | size_t | No | I/Oバッファサイズ | 0以上 |

### 入力データソース

- ファイルシステム上のアーカイブファイル
- メモリバッファ上のアーカイブデータ
- ファイルデスクリプタ（標準入力含む）
- コールバック関数によるカスタムデータソース

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ARCHIVE_OK | int | 正常完了（値: 0） |
| ARCHIVE_EOF | int | アーカイブ末尾到達（値: 1） |
| ARCHIVE_RETRY | int | リトライ可能エラー（値: -10） |
| ARCHIVE_WARN | int | 警告（処理は継続、値: -20） |
| ARCHIVE_FAILED | int | エラー（エントリスキップ可、値: -25） |
| ARCHIVE_FATAL | int | 致命的エラー（値: -30） |

### 出力先

- ファイルシステム（展開先ディレクトリ）
- メモリバッファ
- ファイルデスクリプタ（標準出力含む）
- コールバック関数によるカスタム出力

## 処理フロー

### 処理シーケンス

```
1. アーカイブハンドル作成（archive_read_new / archive_write_new）
   └─ 内部構造体の初期化
2. フォーマット・フィルタ設定
   └─ archive_read_support_format_all / archive_read_support_filter_all
3. 入力ソース指定（archive_read_open_filename等）
   └─ ファイルオープン・バッファ確保
4. エントリ列挙ループ
   └─ archive_read_next_header → archive_entry解析
5. データ読み取り/書き込み
   └─ archive_read_data / archive_write_data
6. ハンドル解放（archive_read_free / archive_write_free）
   └─ リソース解放・ファイルクローズ
```

### フローチャート

```mermaid
flowchart TD
    A[archive_read_new] --> B[フォーマット・フィルタ設定]
    B --> C[archive_read_open_filename]
    C --> D{archive_read_next_header}
    D -->|ARCHIVE_OK| E[エントリメタデータ取得]
    E --> F[archive_read_data / archive_write_data]
    F --> D
    D -->|ARCHIVE_EOF| G[archive_read_free]
    D -->|ARCHIVE_FATAL| H[エラー処理]
    H --> G
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-92-1 | フォーマット自動検出 | 読み込み時にアーカイブ形式を自動判別する | archive_read_support_format_all使用時 |
| BR-92-2 | 圧縮自動検出 | 読み込み時に圧縮形式を自動判別する | archive_read_support_filter_all使用時 |
| BR-92-3 | ストリーミング処理 | データは逐次的に処理され、全体をメモリに保持しない | 常時 |
| BR-92-4 | マジック値検証 | ハンドルの有効性をマジック値で検証する | 全API呼び出し時 |

### 計算ロジック

アーカイブバージョン番号は printf("%d%03d%03d", major, minor, patch) 形式で算出される。例: バージョン3.8.5 は 3008005 となる。

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

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

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ARCHIVE_RETRY (-10) | リトライ可能 | 一時的なエラー | 同じ操作をリトライ |
| ARCHIVE_WARN (-20) | 警告 | 非致命的問題 | archive_error_string()で詳細確認、処理継続可 |
| ARCHIVE_FAILED (-25) | エラー | エントリ処理失敗 | 当該エントリをスキップして次に進む |
| ARCHIVE_FATAL (-30) | 致命的エラー | アーカイブ破損、メモリ不足等 | ハンドルを解放して処理中断 |

### リトライ仕様

ARCHIVE_RETRYが返された場合、同じ操作を再試行可能。ただし実際にRETRYを返すケースは限定的。

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

アーカイブ書き込みは、archive_write_close/archive_write_freeが呼ばれるまでバッファリングされる場合がある。中断時にはアーカイブが不完全な状態で残る可能性がある。

## パフォーマンス要件

- ストリーミングAPIにより、メモリ使用量はアーカイブ全体サイズに依存しない
- ブロックサイズの指定によりI/O効率を調整可能
- 圧縮処理は各圧縮ライブラリに委譲

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

- パストラバーサル攻撃対策: アーカイブエントリのパス名に「..」が含まれる場合の処理
- シンボリックリンク攻撃対策: ARCHIVE_EXTRACT_SECURE_SYMLINKSフラグ
- 所有者復元: ARCHIVE_EXTRACT_OWNERフラグによるUID/GID復元の制御
- setuid/setgidビット: ARCHIVE_EXTRACT_SUID/SGIDフラグで制御
- 暗号化: 一部形式（zip, 7-Zip）で暗号化アーカイブの読み書きをサポート

## 備考

- libarchiveはFreeBSD以外のOS（Linux、macOS等）にも移植されているクロスプラットフォームライブラリである
- バージョン3.8.5がソースツリーに含まれている（ARCHIVE_VERSION_NUMBER = 3008005）
- contrib/libarchive/以下にアップストリームソースが配置されている

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | archive.h | `contrib/libarchive/libarchive/archive.h` | 公開API宣言。バージョン定数（38行目: ARCHIVE_VERSION_NUMBER）、エラーコード定義。archive_read_*/archive_write_*関数群の宣言 |
| 1-2 | archive_entry.h | `contrib/libarchive/libarchive/archive_entry.h` | エントリメタデータのAPI。パス名、パーミッション、所有者、タイムスタンプ等のget/set関数 |
| 1-3 | archive_entry_private.h | `contrib/libarchive/libarchive/archive_entry_private.h` | struct archive_entryの内部構造 |

**読解のコツ**: archive.hの__LA_DECL修飾子はDLL export/import制御用であり、FreeBSD環境では実質的に空文字列。la_int64_tやla_ssize_tはプラットフォーム間の型互換性のためのtypedef。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | archive_read.c | `contrib/libarchive/libarchive/archive_read.c` | archive_read_new, archive_read_open, archive_read_next_header等の実装 |
| 2-2 | archive_write.c | `contrib/libarchive/libarchive/archive_write.c` | archive_write_new, archive_write_open, archive_write_data等の実装 |

**主要処理フロー**:
1. archive_read_new() でハンドル作成・マジック値設定
2. archive_read_support_format_*() でフォーマットハンドラ登録
3. archive_read_support_filter_*() でフィルタ（圧縮）ハンドラ登録
4. archive_read_open_filename() で入力ファイル設定
5. archive_read_next_header() でエントリ列挙

#### Step 3: フォーマットハンドラを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | archive_read_support_format_tar.c | `contrib/libarchive/libarchive/archive_read_support_format_tar.c` | tarフォーマットの読み込み実装 |
| 3-2 | archive_read_support_format_zip.c | `contrib/libarchive/libarchive/archive_read_support_format_zip.c` | zipフォーマットの読み込み実装 |

#### Step 4: フィルタ（圧縮）処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | archive_read_support_filter_xz.c | `contrib/libarchive/libarchive/archive_read_support_filter_xz.c` | xz/lzma圧縮フィルタ |
| 4-2 | archive_read_support_filter_gzip.c | `contrib/libarchive/libarchive/archive_read_support_filter_gzip.c` | gzip圧縮フィルタ |

#### Step 5: FreeBSD固有設定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | config_freebsd.h | `lib/libarchive/config_freebsd.h` | FreeBSD環境向けの設定定義（利用可能な圧縮ライブラリ、機能フラグ等） |
| 5-2 | Makefile | `lib/libarchive/Makefile` | ビルド設定・リンクライブラリ |

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

```
archive_read_new()                    [ハンドル作成]
    │
    ├─ archive_read_support_format_all()  [全フォーマット登録]
    │      ├─ archive_read_support_format_tar()
    │      ├─ archive_read_support_format_zip()
    │      └─ ...
    │
    ├─ archive_read_support_filter_all()  [全フィルタ登録]
    │      ├─ archive_read_support_filter_gzip()
    │      ├─ archive_read_support_filter_xz()
    │      └─ ...
    │
    ├─ archive_read_open_filename()       [ファイルオープン]
    │
    ├─ archive_read_next_header()         [エントリ列挙]
    │      ├─ フォーマットハンドラ.read_header()
    │      └─ archive_entry メタデータ設定
    │
    ├─ archive_read_data()                [データ読み取り]
    │      ├─ フィルタ.read() [解凍]
    │      └─ フォーマットハンドラ.read_data()
    │
    └─ archive_read_free()                [リソース解放]
```

### データフロー図

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

アーカイブファイル     ───▶ archive_read_open_filename() ───▶ ハンドル
(tar.xz等)                     │
                        フィルタチェーン (解凍)
                               │
                        フォーマットハンドラ (ヘッダ解析)
                               │
                        ├─ archive_read_next_header() ───▶ archive_entry
                        └─ archive_read_data()        ───▶ 展開データ
                                                              │
                                                    archive_write_disk
                                                              │
                                                    ファイルシステム出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| archive.h | `contrib/libarchive/libarchive/archive.h` | ヘッダ | 公開API宣言 |
| archive_entry.h | `contrib/libarchive/libarchive/archive_entry.h` | ヘッダ | エントリAPI宣言 |
| archive_read.c | `contrib/libarchive/libarchive/archive_read.c` | ソース | 読み込みコア実装 |
| archive_write.c | `contrib/libarchive/libarchive/archive_write.c` | ソース | 書き込みコア実装 |
| archive_write_disk*.c | `contrib/libarchive/libarchive/` | ソース | ディスク展開実装 |
| archive_check_magic.c | `contrib/libarchive/libarchive/archive_check_magic.c` | ソース | マジック値検証 |
| config_freebsd.h | `lib/libarchive/config_freebsd.h` | 設定 | FreeBSD固有ビルド設定 |
| Makefile | `lib/libarchive/Makefile` | ビルド | ライブラリビルド設定 |
