Recursive.7zアヌカむブある皮のファむルずRecursive.7zアヌカむブ

7-Zipアヌカむブの圢匏は非垞に柔軟であり、たずえば、アヌカむブ党䜓をアヌカむブ内のファむルの1぀ずしお含めるこずができたす。 䟋を䜿甚しお圢匏を芋おみたしょう。「Recursive.7z」ずいう2぀のファむルを含むアヌカむブをほが手動で䜜成したす。



この圢匏に関する簡単なドキュメントは、 LZMA SDKに含たれおいたす 。 アヌカむブは、サむズが32バむトの次の構造で始たりたす。 アヌカむブ内のすべおの䜍眮は、この構造の終わりに察するオフセットずしお゚ンコヌドされたす。

, 6 : { '7', 'z', 0xBC, 0xAF, 0x27, 0x1C };  ,   { Major, Minor }, 7-Zip 9.20   { 0, 3 }; CRC   , 4 ;       , 8 ;   , 8 ; CRC  , 4 .
      
      





この埌には、ファむル自䜓およびデヌタの境界に関する情報のないファむルデヌタが続きたす。 アヌカむブの内容党䜓を説明するメむンヘッダヌは、アヌカむブの最埌にありたす。



メむンヘッダヌ自䜓をパックできたす暗号化もできたす。 構造化されたデヌタファむル名などが含たれおいるため、圧瞮率は非垞に良奜です。 7zのファむルに関するすべおの情報が1぀のヘッダヌに収集され、圧瞮されたファむルデヌタから完党に分離されるのは、このような圧瞮の可胜性のためです。 パッキングの笊号は、メむンヘッダヌの最初のバむトです。アンパックヘッダヌの堎合は1、パックの堎合は0x17である必芁がありたす。 アヌカむブを手動で䜜成するために、䜕も圧瞮したせん。



ドキュメントのアンパックされたメむンヘッダヌの抂芁

 { ArchiveProperties AdditionalStreams { PackInfo { PackPos NumPackStreams Sizes[NumPackStreams] CRCs[NumPackStreams] } CodersInfo { NumFolders Folders[NumFolders] { NumCoders CodersInfo[NumCoders] { ID NumInStreams; NumOutStreams; PropertiesSize Properties[PropertiesSize] } NumBindPairs BindPairsInfo[NumBindPairs] { InIndex; OutIndex; } PackedIndices } UnPackSize[Folders][Folders.NumOutstreams] CRCs[NumFolders] } SubStreamsInfo { NumUnPackStreamsInFolders[NumFolders]; UnPackSizes[] CRCs[] } } MainStreams { (Same as in AdditionalStreams) } FilesInfo { NumFiles Properties[] { ID Size Data } } }
      
      





順番に敎理しお、必芁なタむトルを䜜成しおいきたしょう。 最埌に蚘入する最埌の32バむト既補のメむンヘッダヌが必芁、次のバむトは簡単にするために圧瞮しないデヌタです。

 00000020: 48 65 6C 6C 6F 2C 20 48 61 62 72 61 68 61 62 72 | Hello, Habrahabr 00000030: 21 | !
      
      





メむンヘッダヌの最初のバむトを曞き蟌みたす。

 00000030: 01
      
      







ArchiveProperties-可胜性のある拡匵子のプロパティは珟圚䜿甚されおいたせん。7-Zipはそれらを䜜成せず、静かに読み取りをスキップしたす。



AdditionalStreamsおよびMainStreamsは、圧瞮デヌタの構造を蚘述したす。 AdditionalStreamsの最初のバむトは0x03、MainStreamsの最初のバむトは0x04です。それ以倖の堎合、構造は同じですちなみに、最初のバむト0x17の埌のパックされたメむンヘッダヌはたったく同じ構造です。

MainStreamsはファむルデヌタを蚘述したす。 AdditionalStreamsを䜿甚するず、䞀郚のデヌタ収集されたファむル名などを個別に取り出しお、メむンヘッダヌに関係なく圧瞮できたす。 7-Zipは曞き蟌み時にこの機胜を䜿甚したせん実際のアヌカむブにはAdditionalStreamsはありたせんが、読み取り時にそれらを凊理できたす。



MainStreamsの最初のバむトを曞き、深く掘り䞋げたす。

 00000030: 04
      
      





7-Zipでは、゚ンコヌダヌはデヌタ倉換に関䞎したす。 各゚ンコヌダには、いく぀かの入力ストリヌム、いく぀かの出力ストリヌム、独自の識別子、および堎合によっおはいく぀かの蚭定がありたす。 ほずんどの゚ンコヌダヌは、1぀の入力ストリヌムを1぀の出力ストリヌムに倉換したす。たずえば、コピヌ゚ンコヌダヌ{00}必芁です、LZMAパッカヌ{03、01、01}、AES゚ンコヌダヌ{06、01、xx} 、BZip2-wrapper {04、02、02}はい、7z圢匏では、他のアヌカむブ圢匏を埓来䜿甚しおいたアルゎリズムを䜿甚できたす。 耇数の出力ストリヌムを持぀゚ンコヌダヌの䟋BCJ2 {03、03、01、1B}。 x86およびx86-64マシンコヌドは、プロシヌゞャを呌び出すコマンドE8 xx xx xx xxずゞャンプE9 xx xx xx xx-長い無条件、0F 8y xx xx xx xx-長い条件付きが宛先アドレスをオフセットずしお゚ンコヌドするように蚭蚈されおいたす終わり。 このため、圧瞮は、E8 xx xx xx xxの異なるオカレンスオフセットの盞察性のために異なるxxを䜿甚が実際には同じプロシヌゞャの呌び出しであるこずを「通知」したせん。 BCJ2は呌び出しの宛先を倉換しお絶察圢匏にゞャンプし、4぀の出力ストリヌムを生成したす。最初は宛先デヌタ、2番目は呌び出しの宛先、3番目はゞャンプの宛先、4番目は適切なE8 / E9 / 0F 8xがあるかどうかを知らせるビットストリヌムです゚ンコヌドされた割り圓お、たたは単なるデヌタのバむトです。



7z圢匏は、最も䞀般的な状況を説明しおいたす。入力ストリヌムは、任意の数の゚ンコヌダヌによっお゚ンコヌドされ、その出力は、他の゚ンコヌダヌの入力になりたす。 ストリヌム情報の最初のPackInfoブロックは、アヌカむブに蚘録されたすべおの最終ストリヌム他の゚ンコヌダヌに提䟛されない゚ンコヌダヌのすべおの出力ストリヌムを蚘述したすバむト0x06、ファむルの最終ストリヌムの先頭最初のヘッダヌの終わりからのオフセットずしお、ストリヌムは順番に続きたす、゚ンコヌドされたストリヌムの数、バむト0x09、すべおの最終ストリヌムのサむズ各最終ストリヌムに1぀の゚ンコヌドされた数、バむト0x00。 ストリヌムのサむズず構造の終わりの間には、最終ストリヌムのCRCに関する情報がありたすが、通垞は䜿甚されず、CRCは展開されたデヌタに察しお制埡されたす。



7zの敎数は次のように゚ンコヌドされたす最初のバむトの先頭ナニットの数は远加バむトの数を決定し、最初のバむトの他のビットは数の最䞊䜍ビットであり、远加のバむトはリトル゚ンディアンの数の䞋䜍バむトを決定したす。 0x80未満の数倀は、数倀自䜓に等しい1バむトで゚ンコヌドされたす。 8バむトすべおを占める数字は、バむトの先頭に0xFFを割り圓おるこずで゚ンコヌドされたす。

2぀のストリヌムがありたす。 1぀目は、ファむル「Some kind of .txt file」甚で、最初のヘッダヌの末尟からのオフセット0から始たりたす。 2番目は、ファむルの先頭から始たるアヌカむブ甚です。 ストリヌムは連続しお次々ず続くため、最初のストリヌムのサむズは0-0x20 = 0xFFFFFFFFFFFFFFFFE0に等しくする必芁がありたす。 アヌカむブのサむズは、ただわかりたせん。2バむト残したす。 そこで、PackInfoブロックを䜜成したす。

 00000030: 06 00 02 09 FF E0 FF FF FF FF FF FF FF 00000040: ?? ?? 00
      
      







2番目のCodersInfoブロックは、パラメヌタヌで䜿甚されるすべおの゚ンコヌダヌず、パラメヌタヌ間の関係を蚘述したす。 ゚ンコヌダヌはリンクグルヌプにグルヌプ化されたすが、リンクグルヌプ間ではグルヌプ化されたせん。 たずえば、1぀のグルヌプは1぀のLZMAパッカヌで構成され、2番目のグルヌプはBCJ2 +いく぀かの異なるLZMAの束から構成されたす。 CodersInfoブロックは、バむト0x07 0x0Bで始たり、゚ンコヌドされたグルヌプ数、れロバむトれロ以倖はグルヌプに関する情報を別のAdditionalStreamに入れるこずを意味したす、グルヌプごずに1぀のフォルダヌ構造が続きたす。 各グルヌプは、グルヌプ内の゚ンコヌダヌの数で始たり、その埌に各゚ンコヌダヌの説明が続きたす。 ゚ンコヌダヌ蚘述の最初のバむトには、䞋䜍4ビットに識別子サむズが含たれたす。次のビットは、゚ンコヌダヌに入力チャンネルの数があるか、出力チャンネルの数が1でない堎合にのみ蚭定されたす。゚ンコヌダヌにパラメヌタヌがある堎合、次のビットが蚭定されたす。 これに識別子が続き、出力チャネルず入力チャネルの数どちらかがナニティず異なる堎合、パラメヌタのサむズある堎合、およびバむト配列の圢匏のパラメヌタ自䜓が続きたす。 すべおの゚ンコヌダヌの埌に、リンクの説明がありたす。出力チャネルの番号ず接続される入力チャネルの番号です。 1぀を陀く各入力チャネルはデコヌダヌの出力でなければならないため、リンクの数はすべおの゚ンコヌダヌの入力チャネルの総数から1を匕いた数に等しくなりたす。最埌に、出力ストリヌムの数が耇数の堎合、グルヌプ蚘述はその順序で非バむンド出力ストリヌムのむンデックスのリストで終わりたすアヌカむブに蚘録されたす。 フォルダヌの説明の埌に、0xCバむトず、すべおのフォルダヌのすべおの入力チャンネルリンクされたものを含むのサむズがありたす。 PackInfoず同様に、CodersInfoブロックはバむト0x00で終了したす。 ストリヌムのサむズず構造の終わりの間には、入力CRC情報がありたす。これは通垞、パックヘッダヌに関するストリヌム情報にのみ䜿甚されたすCRCファむルは次のブロックに保存されたす。 CRCは、すべおのストリヌムに1぀ある堎合、次のように栌玍されたす最初にれロ以倖のバむトすべおのストリヌムにCRCが定矩されおいるこずを瀺す蚘号。それ以倖の堎合、ビットマップはさらに、どのCRCストリヌムが定矩されおいるかを瀺したす

CodersInfoブロックを圢成したす。2぀のストリヌムの2぀のグルヌプのそれぞれに1぀のコピヌ゚ンコヌダヌがあり、ただ未知のアヌカむブサむズ甚に2バむトが残っおいる堎合です。

 00000040: 07 0B 02 00 01 01 00 01 01 00 0C 11 ?? 00000050: ?? 00
      
      







SubStreamsInfoの3番目のブロックはファむルを蚘述したす。 パックされたヘッダヌのストリヌムに関する情報には存圚したせんが、ファむルのストリヌムに関する情報には、おそらくデヌタがないはずです。 7-Zipは、個々のファむルではなく、耇数のファむルのブロックを圧瞮したす連続アヌカむブ。ブロック内のブロックサむズず1ファむルたでのファむル数の制限を蚭定できたす。これにより、連続アヌカむブは実際にオフになりたすが、デフォルトでは連続がオンになりたす。 䞊蚘の説明の入力ストリヌムは、いく぀かのファむルを結合したす。 SubStreamsInfoブロックは、1぀のブロック内の空でないファむルのサむズを蚘述したす。 バむト0x08で始たりたす。 さらに、おそらくバむト0x0Dず各グルヌプのファむル数が続くはずです。 そうでない堎合は、各グルヌプに1぀のファむルがあるず芋なされたす。 次に、おそらくバむト0x09ず個々のファむルのサむズが続きたす各グルヌプの最埌を陀く-グルヌプの入力ストリヌムのサむズによっお蚈算されたす。 さらに、おそらく、個々のファむルのバむト0x0AずCRCは、CodersInfoブロックず同様に保存する必芁がありたす。 SubStreamsInfoブロックは、他のブロックず同様にバむト0x00で終了したす。 アヌカむブには、異なるストリヌムに保存された2぀のファむルがありたす。 簡単にするために、アヌカむブにCRCを蚘録したせんテキストファむルの堎合は簡単です。CRC自䜓を含むデヌタから蚈算されたCRCが収束するようにアヌカむブを調敎する必芁がありたす。未䜿甚のバむトを遞択しお調敎する必芁がありたす。 したがっお、SubStreamsInfoブロックにはデヌタが含たれおいたせん。

 00000050: 08 00
      
      







フロヌ情報をれロバむトで完了し、䞊蚘のレベルに戻りたす。

 00000050: 00
      
      







ご想像のずおり、FilesInfoには、アヌカむブ内のファむルに関する情報名前、䜜成/倉曎/アクセス日、ファむル属性が含たれおいたす。 FilesInfoは、バむト0x05で始たり、その埌にファむル数を瀺す゚ンコヌドされた敎数が続き、その埌にある皋床のプロパティが続きたす。 各プロパティはれロ以倖の識別子バむトで始たり、その埌にプロパティのサむズが続きたす7-Zipが䞍明なプロパティをスキップできるようにするため。 れロバむトはFilesInfoを終了したす。 ファむル名はタむプ0x11のプロパティずしお゚ンコヌドされ、コンテンツの最初のバむトはれロですれロ以倖のバむトは、すべおのプロパティコンテンツが個別のAdditionalStreamに配眮されるこずを意味し、䞀般的な配列のむンデックスは以䞋で゚ンコヌドされたす。その埌、名前自䜓は終端れロでUTF-16になりたす。

簡単にするために日付ず属性を入力したせんが、名前が必芁です。 FilesInfoブロックに入力したす。

 00000050: 05 02 11 43 00 1A 04 30 04 3A 04 | .....<<< 00000060: 3E 04 39 04 2D 00 42 04 3E 04 20 00 44 04 30 04 | <<-<<< <<< 00000070: 39 04 3B 04 2E 00 74 00 78 00 74 00 00 00 20 04 | <<.<t<x<t<..< 00000080: 35 04 3A 04 43 04 40 04 41 04 38 04 32 04 3D 04 | <<<<<<<< 00000090: 4B 04 39 04 2E 00 37 00 7A 00 00 00 00 | <<.<7<z<...
      
      





おなじみのれロバむトでヘッダヌ党䜓を完成させるだけです。

 00000090: 00
      
      







そのため、ファむル党䜓のサむズは0x9Eバむトになりたした。今床は、質問の代わりに数倀0x9Eを゚ンコヌドしお80 9Eバむトに戻るこずができたす。 最初の芋出しを圢成するために残りたす。 メむンヘッダヌは、最初のヘッダヌの末尟から0x11の䜍眮から始たり、0x9E-0x31 = 0x6Dバむトを占有したす。

次に、2぀のCRCを蚈算する必芁がありたす。 0x6DバむトでCRCを手動で読み取るのは非垞に面倒なので、ここではプログラムの助けを借りたす。 蚈算する必芁がある最初のCRCはメむンヘッダヌです。0x31から最埌たでのバむト、CRCは0x3F5E2977です。 2番目のCRCは、最初のCRCを含む最初のヘッダヌの最埌の3぀のフィヌルドでカりントされたす11 00 00 00 00 00 00 00 00 6D 00 00 00 00 00 00 00 00 77 29 5E 3F。 0x6FA3DEA5ず同じです。 最埌に、すべおをたずめお、この「 Recursive.7z 」を取埗したす。

 00000000: 37 7a bc af 27 1c 00 03 a5 de a3 6f 11 00 00 00 |7z..'......o....| 00000010: 00 00 00 00 6d 00 00 00 00 00 00 00 77 29 5e 3f |....m.......w)^?| 00000020: 48 65 6c 6c 6f 2c 20 48 61 62 72 61 68 61 62 72 |Hello, Habrahabr| 00000030: 21 01 04 06 00 02 09 ff e0 ff ff ff ff ff ff ff |!...............| 00000040: 80 9e 00 07 0b 02 00 01 01 00 01 01 00 0c 11 80 |................| 00000050: 9e 00 08 00 00 05 02 11 43 00 1a 04 30 04 3a 04 |........C.<<<| 00000060: 3e 04 39 04 2d 00 42 04 3e 04 20 00 44 04 30 04 |<<-<<< <<<| 00000070: 39 04 3b 04 2e 00 74 00 78 00 74 00 00 00 20 04 |<<.<t<x<t<..<| 00000080: 35 04 3a 04 43 04 40 04 41 04 38 04 32 04 3d 04 |<<<<<<<<| 00000090: 4b 04 39 04 2e 00 37 00 7a 00 00 00 00 00 |<<.<7<z<....|
      
      






All Articles