要約

  • 初期の FTP 再開では、送信側と受信側が自分のファイルシステム位置と変換状態を対にして保存した。後の REST STREAM は、次の転送で省くオクテット数を位置とした。
  • 位置は一つの転送表現の座標であって、ファイル版の識別子ではない。パス名、長さ、350 応答だけでは、残った先頭部分と新しい後半が同じ対象に属するとは分からない。
  • RFC 3659 の例は再開前にサーバー上のファイルが変わっていないことを確認済みとする。その確認こそ REST の外側にある安全条件だった。

数字は受理された。それでも対象は未確認だった

大きな取得が 802816 オクテットで途切れたとする。クライアントは接続し直し、TYPE I を選び、REST 802816 を送る。サーバーが 350 を返し、続く RETR は途中からデータを送る。

この応答が保証するのは、次の転送に使う位置をサーバーが保存したことまでである。同じパス名の中身が前回と同じか、手元の部分ファイルがその版の正しい先頭かは答えない。新しい版が十分長ければ、位置は正しくても完成品は旧版と新版の継ぎ合わせになりうる。

異なる機械には異なる座標があった

RFC 765 は、障害回復をチェックポイントからの転送再開として定義した。REST はデータを動かさず、サーバーをマーカー位置へ移し、その直後のサービス命令に再開を任せる。

当時の FTP は、ディスク上の一バイトを世界共通の座標にできなかった。ホストごとに語長、文字コード、行末、レコード構造が違う。格納された論理バイトと、回線を流れる八ビットの転送バイトは区別され、TYPE、STRU、MODE が表現を組み立てた。

RFC 959 の Block と Compressed は、データに区切りのある形式を与える。そこで送信 DTP は本文と区別できる再開マーカーを流へ置き、受信 DTP はそれを自分の保存位置へ対応づけられた。共通の数値体系を作る代わりに、各側が自分の状態を後で再解釈する設計である。

マーカーは耐久性と変換途中も覚えた

RFC 1123 は RFC 959 の 110 応答説明を訂正し、送信側の ssss と受信側の rrrr を一組にした。文字列の意味はローカルでよい。生成した側が再開時にも解釈するからだ。

受信側は rrrr を作る前に、それ以前のデータを安定した記憶へ書き出すべきだとされた。メモリーで受け取っただけの進捗を返せば、障害後にはマーカーだけが残り、対応するデータが消える。

さらに座標は変換器の内部状態を含みうる。TYPE A で回線上の CR LF をローカルの LF 一つに変える場合、CR と LF の間にマーカーが来れば、「CR はすでに見て捨てた」という状態も必要になる。単純なファイル位置だけでは正しい一文字を復元できない。

このため RFC 1123 は、位置を適用できない 554 と、TYPE または STRU が既存の部分ファイルと合わない 555 を加えた。正しい構文は、正しい文脈を意味しない。

STREAM はマーカーを数に変えた

初期の仕組みは周到だが複雑だった。RFC 1123 は 1989 年時点で Restart、ABOR、Block mode を有用だが広く実装されていない堅牢性機能として扱い、REST を最小実装に含めなかった。この記述から現在の普及率を推測することはできない。

Stream mode には本文以外のマーカーブロックを差し込めない。そこで RFC 3659 は、次の転送で実際には送らないオクテット数を REST STREAM の十進値とした。

対応は RFC 2389FEAT で発見できる。サーバーは REST STREAM を掲げるため、クライアントは製品名から能力を推測しなくてよい。ただし能力の存在は、あるパス名の内容が変わっていない証明ではない。

STREAM でも「何のオクテットか」は重要である。RFC 3659 の同一テキストは TYPE I なら SIZE 1830、TYPE A なら 1942 になる。行末変換が送信表現を増やすためだ。再開値は現在の設定で生成されるデータ列の座標であり、いつでもディスクの生位置と一致するわけではない。

送信再開では、サーバーが正しく保存した長さをクライアントが知る必要がある。SIZE はその計算を助けるが、保存済み先頭部分のハッシュではない。

RFC の例が明記した前提

RFC 3659 は 802816 からの再開例で、以前の転送が TYPE I だったことに加え、サーバーのファイルがその後変わっていないと確認済みであることを先に置く。

その一文がなければ、オフセットは別の版にも同じように適用できる。同じ長さの二つのファイルさえ存在する。FTP の終了応答は命令が完了したことを示すが、組み上がった内容が利用者の意図した版かどうかまでは証明しない。

STOR の再開はさらに限定される。RFC 3659 は、以前失敗した転送を完了させる場合にだけ意味を定める。マーカーが既存データ末尾になく、新しいデータでも元の長さまで伸びなければ結果は未定義である。APPE を許す実装も、REST 後は指定位置からの STOR と同じ動作をしなければならない。

命令順もチェックポイントの一部だった

REST は転送命令の直前でなければならない。位置の範囲や再配置の失敗は REST 自体ではなく、続く RETR または STOR で初めて返ることがある。次の命令を送れなかったクライアントは、以前の値が残っていると期待せず REST を送り直す。

したがって実際の再開状態は、部分データ、表現設定、能力、位置、命令順、そしてパス名の外で行う版確認に分散している。一つの数字だけを「再開情報」と呼ぶと、最も重要な条件が見えなくなる。

根拠の範囲

RFC 765 は初期の位置づけ、RFC 959 は転送モード、RFC 1123 は対になった位置と安定記憶、RFC 2389 は能力発見、RFC 3659 は STREAM の数値と SIZE を示す。これらは現代の実装率を測らず、個別サーバーの版保持も証明しない。FTP 再開は認証、内容ハッシュ、スナップショット、exactly-once の仕組みではない。