// ĠCopyright Ġ 2 0 2 2 Ġy u ye zh ong @ gmail . com Ċ // Ċ // ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ // Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ // ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ // Ċ // ĠĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ // Ċ // ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ // Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ // ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ // ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ // Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ċ package Ġcc . c fig . d roid . ota Ċ Ċ import Ġcc . c fig . io . Struct Ċ import Ġc fig . helper . Crypto Helper . Hash er Ċ import Ġc fig . helper . Helper Ċ import Ġc fig . helper . Dump ling Ċ import Ġchrome os _ update _ engine . Update Metadata Ċ import Ġcom . fasterxml . jackson . annotation . JsonInclude Ċ import Ġcom . fasterxml . jackson . databind . ObjectMapper Ċ import Ġcom . google . protobuf . ByteString Ċ import Ġorg . apache . commons . exec . CommandLine Ċ import Ġorg . apache . commons . exec . Default Executor Ċ import Ġorg . apache . commons . exec . Pump Stream Handler Ċ import Ġorg . slf 4 j . LoggerFactory Ċ import Ġjava . io .* Ċ import Ġjava . nio . file . Files Ċ import Ġjava . nio . file . Paths Ċ import Ġjava . time . Instant Ċ import Ġjava . time . Zone Id Ċ import Ġjava . time . format . DateTime Formatter Ċ Ċ class ĠPayload Ġ{ ĊĠĠĠ Ġvar ĠfileName : ĠString Ġ= Ġ"" ĊĠĠĠ Ġvar Ġheader Ġ= ĠPayload Header () ĊĠĠĠ Ġvar Ġmanifest : ĠUpdate Metadata . Delta Archive Manifest Ġ= ĠUpdate Metadata . Delta Archive Manifest . newBuilder (). build () ĊĠĠĠ Ġvar Ġmeta Sig : ĠUpdate Metadata . Signatures Ġ= ĠUpdate Metadata . Signatures . newBuilder (). build () ĊĠĠĠ Ġvar Ġmeta Size : ĠInt Ġ= Ġ 0 ĊĠĠĠ Ġvar Ġdata Offset : ĠLong Ġ= Ġ 0 L ĊĠĠĠ Ġvar Ġdata Sig : ĠUpdate Metadata . Signatures Ġ= ĠUpdate Metadata . Signatures . newBuilder (). build () ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġlog Ġ= ĠLoggerFactory . getLogger ( Payload :: class . java ) ĊĠĠĠĠĠĠĠ Ġval Ġwork Dir Ġ= ĠHelper . prop (" payload Dir ") ĊĊĠĠĠĠĠĠĠ Ġfun Ġparse ( in FileName : ĠString ): ĠPayload Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġret Ġ= ĠPayload () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġret . fileName Ġ= Ġin FileName ĊĠĠĠĠĠĠĠĠĠĠĠ ĠFileInputStream ( in FileName ). use Ġ{ Ġfis Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġret . header Ġ= ĠPayload Header ( fis ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġret . meta Size Ġ= Ġret . header . header Size Ġ+ Ġret . header . manifest Len . toInt () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġret . data Offset Ġ= Ġ( ret . meta Size Ġ+ Ġret . header . meta Sig Len ). to Long () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// manifest ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġret . manifest Ġ= ĠByteArray ( ret . header . manifest Len . toInt ()). let Ġ{ Ġbuf Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfis . read ( buf ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠUpdate Metadata . Delta Archive Manifest . parseFrom ( buf ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// meta Ġsig ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġret . meta Sig Ġ= ĠByteArray ( ret . header . meta Sig Len ). let Ġ{ Ġbuf 2 Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfis . read ( buf 2 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠUpdate Metadata . Signatures . parseFrom ( buf 2 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// data Ġsig ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( ret . manifest . has Signatures Offset ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . debug (" payload Ġsig Ġoffset Ġ= Ġ" Ġ+ Ġret . manifest . signatures Offset ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . debug (" payload Ġsig Ġsize Ġ= Ġ" Ġ+ Ġret . manifest . signatures Size ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfis . skip ( ret . manifest . signatures Offset ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġret . data Sig Ġ= ĠByteArray ( ret . manifest . signatures Size . toInt ()). let Ġ{ Ġbuf Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfis . read ( buf ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠUpdate Metadata . Signatures . parseFrom ( buf ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . warn (" payload Ġhas Ġno Ġsignatures ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġ// end - of - fis ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġrun Ġ{// CHECK _ EQ ( payload . size (), Ġsignatures _ offset Ġ+ Ġmanifest . signatures _ size ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcalculated Size Ġ= Ġret . header . header Size Ġ+ Ġret . header . manifest Len Ġ+ Ġret . header . meta Sig Len Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġret . manifest . signatures Offset Ġ+ Ġret . manifest . signatures Size ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( File ( in FileName ). length () Ġ== Ġcalculated Size ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info (" payload . bin Ġsize Ġinfo Ġcheck ĠPASS ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalStateException (" calculated Ġpayload Ġsize Ġdoesn 't Ġmatch Ġfile Ġsize ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcalc Metadata Hash Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠHash er . hash ( Dump ling ( in FileName ), ĠlistOf ( Pair ( 0 L , Ġret . meta Size . to Long ())), Ġ" sha - 2 5 6 ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info (" calc Ġmeta Ġhash : Ġ" Ġ+ ĠHelper . to HexString ( calc Metadata Hash )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcalc Payload Hash Ġ= ĠHash er . hash ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠDump ling ( in FileName ), ĠlistOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPair ( 0 L , Ġret . meta Size . to Long ()), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPair ( ret . meta Size . to Long () Ġ+ Ġret . header . meta Sig Len , Ġret . manifest . signatures Offset ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ), Ġ" sha - 2 5 6 " ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcheck ( calc Payload Hash . size Ġ== Ġ 3 2 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info (" calc Ġpayload Ġhash : Ġ" Ġ+ ĠHelper . to HexString ( calc Payload Hash )) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġread Payload Signature Ġ= ĠUpdate Metadata . Signatures . parseFrom ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠHelper . read Fully ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġin FileName , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġret . data Offset Ġ+ Ġret . manifest . signatures Offset , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġret . manifest . signatures Size . toInt () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info (" Found Ġsig Ġcount : Ġ" Ġ+ Ġread Payload Signature . signatures Count ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġread Payload Signature . signatures List . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// pass ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info ( it . data . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info (" sig _ data Ġsize Ġ= Ġ" Ġ+ Ġit . data . toByteArray (). size ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info ( Helper . to HexString ( it . data . toByteArray ())) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠFiles . write ( Paths . get (" sig _ data "), Ġit . data . toByteArray ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġret ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġclass ĠPayload Verifier Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfun Ġget Raw Hash From Signature ( sig _ data : ĠByte String , Ġpub key : ĠString , Ġsig Hash : ĠByteArray ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġdisplay Signature Blob ( sig Name : ĠString , Ġsig : ĠUpdate Metadata . Signatures ): ĠString Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠStringBuilder (). let Ġ{ Ġsb Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsb . append ( String . format ("% s Ġsignatures : Ġ(% d Ġentries )\ n ", Ġsig Name , Ġsig . signatures Count )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsig . signatures List . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsb . append ( String . format (" Ġ Ġhex _ data : Ġ(% d Ġbytes )\ n ", Ġit . data . size ())) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsb . append (" Ġ ĠData : Ġ" Ġ+ ĠHelper . to HexString ( it . data . toByteArray ()) Ġ+ Ġ"\ n ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsb ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. toString () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġprint Info () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġmi Ġ= ĠManifest Info ( block Size Ġ= Ġthis . manifest . block Size , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġminor Version Ġ= Ġthis . manifest . minor Version , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmax TimeStamp Ġ= Ġthis . manifest . max Timestamp , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsignature Offset Ġ= Ġthis . manifest . signatures Offset , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsignature Size Ġ= Ġthis . manifest . signatures Size , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpartial Update Ġ= Ġthis . manifest . has Partial Update (), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġparts ToUpdate Ġ= Ġthis . manifest . partitions List . map Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠManifest Info . Partition ToUpdate ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . partition Name , Ġit . operations Count , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . has Run Post install ()) Ġit . run Post install Ġelse Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . has Post install Path ()) Ġit . post install Path Ġelse Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠ Ġenable Snapshot Ġ= Ġthis . manifest . dynamic Partition Metadata . has Snapshot Enabled (), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdynamic Groups Ġ= Ġthis . manifest . dynamic Partition Metadata . groups List . map Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠManifest Info . Dynamic Part Group ( name Ġ= Ġit . name , Ġsize Ġ= Ġit . size , Ġpart Name Ġ= Ġit . partition Names List ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠĠĠĠĠ ĠObjectMapper (). writer WithDefault PrettyPrinter (). writeValue ( File ("$ work Dir / header . json "), Ġthis . header ) ĊĠĠĠĠĠĠĠ Ġlog . info (" Ġ Ġheader Ġ Ġinfo Ġdumped Ġto Ġ${ work Dir } header . json ") ĊĠĠĠĠĠĠĠ ĠObjectMapper (). writer WithDefault PrettyPrinter (). writeValue ( File ("$ work Dir / manifest . json "), Ġmi ) ĊĠĠĠĠĠĠĠ Ġlog . info (" Ġmanifest Ġinfo Ġdumped Ġto Ġ${ work Dir } manifest . json ") ĊĊĠĠĠĠĠĠĠ Ġval Ġsignature File Ġ= Ġ"${ work Dir } signatures . txt " ĊĠĠĠĠĠĠĠ ĠFileOutputStream ( signature File , Ġfalse ). use Ġ{ Ġf os Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġf os . writer (). use Ġ{ Ġf Writer Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġf Writer . write ("< Metadata > Ġsignatures : Ġoffset =" Ġ+ Ġthis . header . manifest Len Ġ+ Ġ", Ġsize =" Ġ+ Ġthis . header . meta Sig Len Ġ+ Ġ"\ n ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġf Writer . write ( Payload . display Signature Blob ("< Metadata >", Ġthis . meta Sig )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġf Writer . write ("< Payload > Ġsignatures : Ġbase = Ġoffset =" Ġ+ Ġmanifest . signatures Offset Ġ+ Ġ", Ġsize =" Ġ+ Ġthis . header . meta Sig Len Ġ+ Ġ"\ n ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġf Writer . write (( Payload . display Signature Blob ("< Payload >", Ġthis . data Sig ))) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġlog . info (" signature Ġinfo Ġdumped Ġto Ġ$ signature File ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġde compress ( in Bytes : ĠByteArray , Ġop Type : ĠUpdate Metadata . Install Operation . Type ): ĠByteArray Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġba os O Ġ= ĠByteArrayOutputStream () ĊĠĠĠĠĠĠĠ Ġval Ġba os E Ġ= ĠByteArrayOutputStream () ĊĠĠĠĠĠĠĠ Ġval Ġb ais Ġ= ĠByteArrayInputStream ( in Bytes ) ĊĠĠĠĠĠĠĠ ĠDefault Executor (). let Ġ{ Ġexec Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexec . stream Handler Ġ= ĠP ump Stream Handler ( ba os O , Ġba os E , Ġb ais ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcmd Ġ= Ġwhen Ġ( op Type ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠUpdate Metadata . Install Operation . Type . REPLACE _ XZ Ġ-> ĠCommandLine (" xz cat ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠUpdate Metadata . Install Operation . Type . REPLACE _ BZ Ġ-> ĠCommandLine (" bz cat ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠUpdate Metadata . Install Operation . Type . REPLACE Ġ-> Ġreturn Ġin Bytes ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġthrow ĠIllegalArgumentException ( op Type . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcmd . add Argument ("- ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexec . execute ( cmd ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġba os O . toByteArray () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġunpack Internal ( ras : ĠRandom Access File , Ġpu : ĠUpdate Metadata . Partition Update , Ġlog Prefix : ĠString Ġ= Ġ"") Ġ{ ĊĠĠĠĠĠĠĠ Ġlog . info ( String . format ("[ % s ] Ġextracting Ġ% 1 3 s . img Ġ(% d Ġops )", Ġlog Prefix , Ġpu . partition Name , Ġpu . operations Count )) ĊĠĠĠĠĠĠĠ ĠFileOutputStream ("$ work Dir /${ pu . partition Name }. img "). use Ġ{ Ġout File Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġops Ġ= Ġpu . operations List . to Mutable List (). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠsortBy Ġ{ Ġit . get Dst Ext ents ( 0 ). start Block Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġops . forEach Ġ{ Ġop Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . debug ( pu . partition Name Ġ+ Ġ": Ġ" Ġ+ Ġ( op . get Dst Ext ents ( 0 ). start Block Ġ* Ġthis . manifest . block Size ) Ġ+ Ġ", Ġsize =" Ġ+ Ġop . data Length ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpiece Ġ= ĠByteArray ( op . data Length . toInt ()). let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġr as . seek ( this . data Offset Ġ+ Ġop . data Offset ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġr as . read ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġout File . write ( de compress ( piece , Ġop . type )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun ĠsetUp () Ġ{ ĊĠĠĠĠĠĠĠ ĠFile ( work Dir ). let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . exists ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info (" Removing Ġ$ work Dir ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . delete Re cursively () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info (" Creating Ġ$ work Dir ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . mkdir s () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġunpack () Ġ{ ĊĠĠĠĠĠĠĠ ĠRandom Access File ( this . fileName , Ġ" r "). use Ġ{ Ġr as Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġcurrent Num Ġ= Ġ 1 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtotal Num Ġ= Ġthis . manifest . partitions Count ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġparts Ġ= Ġthis . manifest . partitions List . map Ġ{ Ġit . partition Name Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info (" There Ġare Ġ$ total Num Ġpartitions Ġ$ parts ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info (" dump ing Ġimages Ġto Ġ$ work Dir ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis . manifest . partitions List . forEach Ġ{ Ġpu Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġunpack Internal ( ras , Ġpu , ĠString . format ("% 2 d /% d ", Ġcurrent Num , Ġtotal Num )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent Num ++ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġdata Ġclass ĠPayload Header ( ĊĠĠĠĠĠĠĠ Ġvar Ġversion : ĠLong Ġ= Ġ 0 , ĊĠĠĠĠĠĠĠ Ġvar Ġmanifest Len : ĠLong Ġ= Ġ 0 , ĊĠĠĠĠĠĠĠ Ġvar Ġmeta Sig Len : ĠInt Ġ= Ġ 0 , ĊĠĠĠĠĠĠĠ Ġvar Ġheader Size : ĠInt Ġ= Ġ 0 ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġmagic Ġ= Ġ" Cr AU " ĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠFORMAT _ STRING Ġ= Ġ"> 4 sq q " Ġ// magic , Ġversion , Ġmanifest Len ĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠCH ROME OS _ MAJOR _ PAYLOAD _ VERSION Ġ= Ġ 1 L ĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠBR IL LO _ MAJOR _ PAYLOAD _ VERSION Ġ= Ġ 2 L ĊĠĠĠĠĠĠĠ Ġval ĠtypeOf Version : ĠString ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġwhen Ġ( version ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠCH ROME OS _ MAJOR _ PAYLOAD _ VERSION Ġ-> Ġ" chrome Os " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBR IL LO _ MAJOR _ PAYLOAD _ VERSION Ġ-> Ġ" br illo " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġthrow ĠIllegalArgumentException () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġconstructor ( fis : ĠInputStream ) Ġ: Ġthis () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġinfo Ġ= ĠStruct ( FORMAT _ STRING ). unpack ( fis ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcheck (( info [ 0 ] Ġas ĠString ) Ġ== Ġmagic ) Ġ{ Ġ"${ info [ 0 ]} Ġis Ġnot Ġpayload Ġmagic " Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġversion Ġ= Ġinfo [ 1 ] Ġas ĠLong ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmanifest Len Ġ= Ġinfo [ 2 ] Ġas ĠLong ĊĠĠĠĠĠĠĠĠĠĠĠ Ġheader Size Ġ= ĠStruct ( FORMAT _ STRING ). calc Size () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( version Ġ== ĠBR IL LO _ MAJOR _ PAYLOAD _ VERSION ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġheader Size Ġ+= ĠInt . SIZE _ BYTES ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmeta Sig Len Ġ= ĠStruct ("> i "). unpack ( fis )[ 0 ] Ġas ĠInt ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ JsonInclude ( JsonInclude . Include . NON _ NULL ) ĊĠĠĠ Ġdata Ġclass ĠManifest Info ( ĊĠĠĠĠĠĠĠ Ġvar ĠblockSize : ĠInt ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠ Ġvar Ġminor Version : ĠInt ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠ Ġvar Ġmax TimeStamp : ĠLong Ġ= Ġ 0 L , ĊĠĠĠĠĠĠĠ Ġvar Ġmax Time Readable : ĠString ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠ Ġvar Ġpartial Update : ĠBoolean ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠ Ġval Ġsignature Offset : ĠLong ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠ Ġval Ġsignature Size : ĠLong ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠ Ġvar Ġdynamic Groups : ĠList < Dynamic Part Group > Ġ= ĠlistOf (), ĊĠĠĠĠĠĠĠ Ġvar Ġenable Snapshot : ĠBoolean ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠ Ġvar Ġparts ToUpdate : ĠList < Partition ToUpdate > Ġ= ĠlistOf () ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġl dt Ġ= ĠInstant . of Epoch Milli ( max TimeStamp Ġ* Ġ 1 0 0 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. at Zone ( Zone Id . system Default ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. to LocalDateTime () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmax Time Readable Ġ= ĠDateTime Formatter . ISO _ LOCAL _ DATE _ TIME . format ( ld t ) Ġ+ Ġ" Ġ(${ Zone Id . system Default () })" ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ@ JsonInclude ( JsonInclude . Include . NON _ NULL ) ĊĠĠĠĠĠĠĠ Ġdata Ġclass ĠPartition ToUpdate ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġname : ĠString Ġ= Ġ"", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġops : ĠInt Ġ= Ġ 0 , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġrun Post Install : ĠBoolean ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġpost Install Path : ĠString ? Ġ= Ġnull ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠ Ġdata Ġclass ĠDynamic Part Group ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġname : ĠString Ġ= Ġ"", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġsize : ĠLong Ġ= Ġ 0 L , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġpart Name : ĠList < String > Ġ= ĠlistOf () ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} Ċ } Ċ