NimTarは特にLinuxで普及しているアーカイブ形式。英語圏でTarballなどとも呼ばれます。複数のファイルやディレクトリ構造を一つのtarファイルにまとめることができますが、あくまでもアーカイブ用途のコンテナなので、サイズを減らすには圧縮形式(gzipなど)を併用する必要があります。ご存知の通り拡張子は.tar。tar.xzは、tarでアーカイブした後に圧縮したもの(たぶん)、なので、展開したい場合は逆に伸長(decompress)した後に分割(unarchive)、という手順になります。Linuxにはtarコマンドがあるのでそう困ることはありませんが、Windowsではちょっと事情が違います。Windowsではアーカイブ、圧縮ともにzip形式が一般的なのでそう使う頻度は高くありませんが、稀によくtarを扱う必要に迫られる場面があります。今回はTarの仕様と、簡単な実装についてメモしておきます。(typeflag)マジックナンバーとバージョン実装例の調査アーカイブの構造NimのパッケージマネージャNimbleのインデックスを見ていると、展開側(untar)はあるようですがアーカイブ作成側はないようですね。練習がてら、ゆるっとした仕様で作成してみることにします。content)を連結していけばいいみたいですね。歴史の長い形式だけあって、実装形式が複数存在するようです。tarに寄せておけば大抵のソフトウェアと互換性の面で問題なさそうです。tarっぽく実用的な範囲で実装できればよいことにします。archive)を付けるただし、ヘッダが固定長なことに由来して色々と制約が生じていることから、各形式で拡張が加えられています。拡張のやり方は形式毎に異なっていますが、基本的には互換性のためにヘッダはそのまま、かつ拡張したメタデータをコンテントに書く、という方針のようです。pad[12];};ユーザやグループなど、UnixでサポートされているメタデータはWindowsでは直接対応するものがないこともあり、今回はハードコーディングします。実際手元のマシンで試した限りでは、Windows向けの実装では無視されていることが多いようです。長いパスヘッダのファイル名用フィールドname[100]には相対パスを格納します。仕様上は絶対パスを許容しているようですが、あまり使われていないもよう。素のファイル名用フィールドは100バイト、ustarでプレフィクス用フィールドを使っても255バイトまで。Ascii英数なら1バイト1文字、なので二百と何十文字の計算になりますが、ちょっとディレクトリ階層が深くなったり、日本語などのマルチバイト文字(1文字~4バイトとか)を使うとすぐに枯渇します。tarではLフラグを使って、長いパスをコンテントのほうに書く、という拡張を実装しているようなので、今回はこれに倣います。長いパスを表すヘッダでは、"././@LongLink"が固定でファイル名フィールドname[100]に入ります。順番として、Lフラグのヘッダ、パスを格納したコンテント、以降に通常のヘッダ...、と並びます。通常のヘッダに格納されているファイル名は不完全なので展開時には使いません。ustarでは、プレフィクス用のフィールドも使う仕様になっています。100バイトを超えるパスの場合は、セパレータ(‘/’や’\’)を境に、ファイル名用フィールドname[100]と、プレフィクス用のフィールドprefix[155]に分けて格納される可能性があります。フィールドに格納された文字列は、バイナリゼロ’\0’に到達するまでの範囲が有効であるとみなされます。Pax交換フォーマットでは拡張用ヘッダに”PaxHeaders”を含むパスがこのファイル名フィールドname[100]に入ります。「tarを展開したら変な名前のディレクトリ/ファイルが出てきた!」という問題は、たいていこのあたりの拡張に原因があるので、ちゃんと形式を合わせてやれば読むことができます。ファイルサイズファイルサイズ用のフィールドは12バイト、ヌル終端込み。拡張を考えなければ11桁の8進数でファイルサイズのバイト数を表します。古い形式に8GBのサイズ制限があるのは、ここに理由があるんですね。まあ最近でも8GBを越えるファイルを、しかもアーカイブしたいという用途はあまり無いと思いますので、ここは素のままにしておきます。ディレクトリの場合(‘5’フラグ)の場合はサイズがゼロになります。‘L’フラグ、長いパスを格納するためのヘッダでは、ファイルサイズのところにパスの長さ(バイト数)が入ります。チェックサムちゃんとしたアーカイバはチェックサムでヘッダの内容をチェックしています。int)で表した場合の総和(8進数)がチェックサムになります。したがって、MD5やAESなどのような強固なハッシュではなく、今となってはあくまでもデバッグに使える程度のものと言っていいと思います。intへの変換は、最適化するとうまいやり方がありますが、簡便には型のキャストで計算できます。ヘッダにはチェックサムのフィールド自身が含まれるので、計算する際には(ヌル終端なし)長さ8の連続した空白で仮に埋めておいて計算します。計算した結果は8進数6桁の数値で表します。上位桁をゼロパディングして最後の桁は空白を入れます。‘\0’)か、ディレクトリ(‘5’)か、シンボリックリンクか、などの種類を判別するためのものです。今回は実装を簡単にするため、ファイルとディレクトリのみ考慮します。Pax交換フォーマットでは拡張用ヘッダに”x”が入るようです。マジックナンバーとバージョンこれも実装により異なります。Hexで書くとこんな感じ。(というかGNU/Linux)では大抵バンドルされているところのtarコマンドで形式が指定できます。utilsなど圧縮ライブラリとも連携しますので、サイズを減らしたい場合でも困ることはないと思います。path"問題はWindowsで、参考のためいくつかのソフトウェアでデフォルトの実装を調べてみました。tarを出力しますが、公式マニュアルによると他の形式もサポートしています。終端(end-of-archive)がやたらと長い気が。ソースを読めば分かるのでしょうが、まあ実装上は問題にならないので気にしないことにしましょう。tarっぽいLフラグを使う、というよくわからない実装になっています。私が誤解しているのでしょうか。tarが、ここで比較した中では最も厳密に実装されているように見えます。他の実装ではuidやgidをゼロパディングやバイナリゼロにしていますが、WindowsでもちゃんとユーザIDを拾おうとしているようですね。tar形式)のバイナリ表示の例を掲載しておきます。絵を作るだけで力尽きたので、説明は省略します。例によって長くなりましたので、続きは実装編で。usta関連記事PythonとNimでXZ圧縮を利用するファイル圧縮の形式は世にいろいろありますが、昨今はzipがもっとも一般的でしょうか。zipは圧縮・展開にかかる時間もほどほど、圧縮率もほ...記事を読むNimコンパイラをWindowsにインストールするNimのWindows向けインストール方法をメモしておきます。検証した環境は以下の通り。~続・ちゃぶだい返し(実装編)~前記事の実装編です。Nimでtarの作成(アーカイブ)と伸長の処理を実装します。コメントをキャンセルメールアドレスが公開されることはありません。コメントデータの処理方法の詳細はこちらをご覧ください。