Ë €ŠT¢GøŽ:ãó—dZddlZddlZddlZddlZddlZddlZddlZddlm Z ddl m Z ddl m ZddlmZddlmZdd lmZej*e«Zd ZGd „d e«ZGd „d«ZGd„de«ZGd„de«Zy)a… This module implements copying of images with bmap and provides the following API. 1. BmapCopy class - implements copying to any kind of file, be that a block device or a regular file. 2. BmapBdevCopy class - based on BmapCopy and specializes on copying to block devices. It does some more sanity checks and some block device performance tuning. The bmap file is an XML file which contains a list of mapped blocks of the image. Mapped blocks are the blocks which have disk sectors associated with them, as opposed to holes, which are blocks with no associated disk sectors. In other words, the image is considered to be a sparse file, and bmap basically contains a list of mapped blocks of this sparse file. The bmap additionally contains some useful information like block size (usually 4KiB), image size, mapped blocks count, etc. The bmap is used for copying the image to a block device or to a regular file. The idea is that we copy quickly with bmap because we copy only mapped blocks and ignore the holes, because they are useless. And if the image is generated properly (starting with a huge hole and writing all the data), it usually contains only little mapped blocks, comparing to the overall image size. And such an image compresses very well (because holes are read as all zeroes), so it is beneficial to distributor them as compressed files along with the bmap. Here is an example. Suppose you have a 4GiB image which contains only 100MiB of user data and you need to flash it to a slow USB stick. With bmap you end up copying only a little bit more than 100MiB of data from the image to the USB stick (namely, you copy only mapped blocks). This is a lot faster than copying all 4GiB of data. We say that it is a bit more than 100MiB because things like file-system meta-data (inode tables, superblocks, etc), partition table, etc also contribute to the mapped blocks and are also copied. éN)Úreraise)Úqueue)Ú_thread)ÚOptional)Ú ElementTreeé)Ú human_sizez2.0có—eZdZdZy)ÚErrorzË A class for exceptions generated by the 'BmapCopy' module. We currently support only one type of exceptions, and we basically throw human-readable problem description in case of errors. N)Ú__name__Ú __module__Ú __qualname__Ú__doc__©óú6/usr/lib/python3.12/site-packages/bmaptool/BmapCopy.pyr r Os „ñð  rr cób—eZdZdZej d«Zd dededdfd„Zd„Z d „Z d „Z d „Z y) Ú SysfsChangea?Context manager for temporary sysfs changes Writes a temporary value to a sysfs file and restores the original value upon exit. Does a read access first to see if the requested value is already set. In that case, no write access is made to not cause unnecessary errors when running as a non-root user. Can deal with sysfs files that return their plain current value upon reading, as well as those that return all possible values with the current one in square brackets. In this case, all possible values are stored in the `options` attribute. z!([^\[\]]*)\[([^ \]]+)\]([^\[\]]*)ÚpathÚ temp_valueÚreturnNcóf—||_||_||_d|_d|_g|_d|_y)avThe class constructor. The parameters are: path - The sysfs file to change temp_value - The value to set upon entering the context manager suppress_ioerrors - When True, an IOError during __enter__ is stored to the `error` attribute. When False, the exception is raised directly. ÚFN)rrÚsuppress_ioerrorsÚ old_valueÚmodifiedÚoptionsÚerror)Úselfrrrs rÚ__init__zSysfsChange.__init__fs6€ðˆŒ Ø$ˆŒØ!2ˆÔ؈ŒØˆŒ ؈Œ Ø(,ˆ� rcó`—t|jd«5}|j«j«}ddd«|jj «}|rGdj |j«dd«jd«|_ |jd«S|S#1swYŒoxYw)NÚrrréÚ é) ÚopenrÚreadÚstripÚre_current_selectionÚmatchÚjoinÚgroupsÚsplitrÚgroup)rÚfÚcontentsr*s rÚ_readzSysfsChange._readvsˆ€Ü �$—)‘)˜SÔ ! QØ—v‘v“x—~‘~Ó'ˆH÷"ð ×)Ñ)×/Ñ/°Ó9ˆÙ ØŸ7™7 5§<¡<£>°!°AÐ#6Ó7×=Ñ=¸cÓBˆDŒLØ—;‘;˜q“>Ð !àˆO÷"Ð !ús —B$Â$B-có|—t|jd«5}|j|«ddd«y#1swYyxYw)NÚw)r&rÚwrite)rÚvaluer/s rÚ_writezSysfsChange._write„s)€Ü �$—)‘)˜SÔ ! QØ �G‰G�EŒN÷"× !Ñ !ús—2²;có— |j«|_tjd|j›d|j›d�«|j|jk7rU tjd|j›d|j›d�«|j|j«d|_ |S|S#t $r }|j r||_|cYd}~S‚d}~wwxYw#t $r }|j r||_n‚Yd}~|Sd}~wwxYw)Nzfound z to be 'Ú'úsetting ú to 'T) r1rÚ_logÚdebugrÚIOErrorrrrr6r)rÚexcs rÚ __enter__zSysfsChange.__enter__ˆsï€ð Ø!ŸZ™Z›\ˆDŒNÜ �J‰J˜ § ¡ ˜{¨(°4·>±>Ð2BÀ!ÐDÔ Eð �>‰>˜TŸ_™_Ò ,ð Ü— ‘ ˜X d§i¡i [°°d·o±oÐ5FÀaÐHÔIØ— ‘ ˜DŸO™OÔ,Ø $�” ð ˆ ˆtˆ øô#ò Ø×%Ò%Ø �” Ø• àûð  ûôò Ø×)Ò)Ø!$�D•Jàóðˆ ûð  ús=‚AB7Á!AC#Â7 C ÃCÃC ÃCÃC Ã# D Ã,DÄD c ó(—|jrM tjd|j›d|j›d�«|j |j«yy#t $r-}td|j›d|j›d|›�«‚d}~wwxYw)Nr9z back to 'r8zcannot restore r:ú': F)rr;r<rrr6r=r )rÚexc_typeÚ exc_valueÚexc_tbr>s rÚ__exit__zSysfsChange.__exit__Ÿs…€Ø �=Š=ð XÜ— ‘ ˜X d§i¡i [° ¸4¿>¹>Ð:JÈ!ÐLÔMØ— ‘ ˜DŸN™NÔ+ñøôò Xܘo¨d¯i©i¨[¸¸d¿n¹nÐ=MÈSÐQTÐPUÐVÓWÐWûð XúsŽA AÁ BÁ$(B  B)T) r r rrÚreÚcompiler)Ústrr r1r6r?rErrrrrYsI„ñð&˜2Ÿ:™:Ð&JÓKÐñ-˜Sð-¨cð-Èdó-ò òòó.rrcó\—eZdZdZdd„Zd„Zd„Zd„Zd„Zd„Z d „Z d „Z d „Z d „Z dd „Zd„Zy)ÚBmapCopya` This class implements the bmap-based copying functionality. To copy an image with bmap you should create an instance of this class, which requires the following: * full path or a file-like object of the image to copy * full path or a file object of the destination file copy the image to * full path or a file object of the bmap file (optional) * image size in bytes (optional) Although the main purpose of this class is to use bmap, the bmap is not required, and if it was not provided then the entire image will be copied to the destination file. When the bmap is provided, it is not necessary to specify image size, because the size is contained in the bmap. Otherwise, it is benefitial to specify the size because it enables extra sanity checks and makes it possible to provide the progress bar. When the image size is known either from the bmap or the caller specified it to the class constructor, all the image geometry description attributes ('blocks_cnt', etc) are initialized by the class constructor and available for the user. However, when the size is not known, some of the image geometry description attributes are not initialized by the class constructor. Instead, they are initialized only by the 'copy()' method. The 'copy()' method implements image copying. You may choose whether to verify the checksum while copying or not. Note, this is done only in case of bmap-based copying and only if bmap contains checksums (e.g., bmap version 1.0 did not have checksums support). You may choose whether to synchronize the destination file after writing or not. To explicitly synchronize it, use the 'sync()' method. This class supports all the bmap format versions up version 'SUPPORTED_BMAP_VERSION'. It is possible to have a simple progress indicator while copying the image. Use the 'set_progress_indicator()' method. You can copy only once with an instance of this class. This means that in order to copy the image for the second time, you have to create a new class instance. Ncó†—d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_ d|_ d|_ d|_ d|_ d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_|j1dd«d|_||_|j6|_||_|j6|_t?j@|j:jC««}tEjF|jH«|_%d|_&d|_'d|_(d|_)tEjT|jH«rLt?jV|jX«dk(r*t?jZ|jX«dk(rd|_.nd|_.|r)||_|j6|_/|ja«nd|_d |_ d |_|r|jc|«|j|jz|_y) a  The class constructor. The parameters are: image - file-like object of the image which should be copied, should only support 'read()' and 'seek()' methods, and only seeking forward has to be supported. dest - file object of the destination file to copy the image to. bmap - file object of the bmap file to use for copying. image_size - size of the image in bytes. Niérr#FTriéd)2Ú_xmlÚ_dest_fsync_watermarkÚ _batch_blocksÚ _batch_queueÚ _batch_bytesÚ_batch_queue_lenÚ bmap_versionÚbmap_version_majorÚbmap_version_minorÚ block_sizeÚ blocks_cntÚ mapped_cntÚ image_sizeÚimage_size_humanÚ mapped_sizeÚmapped_size_humanÚmapped_percentÚ_f_bmapÚ _f_bmap_pathÚ_progress_startedÚ_progress_indexÚ_progress_timeÚ_progress_fileÚ_progress_formatÚset_progress_indicatorÚ _psplash_pipeÚ_f_imageÚnameÚ _image_pathÚ_f_destÚ _dest_pathÚosÚfstatÚfilenoÚstatÚS_ISREGÚst_modeÚ_dest_is_regfileÚ_cs_typeÚ_cs_lenÚ_cs_attrib_nameÚ_bmap_cs_attrib_nameÚS_ISCHRÚmajorÚst_rdevÚminorÚ_dest_supports_fsyncÚ _bmap_pathÚ _parse_bmapÚ_set_image_size)rÚimageÚdestÚbmaprZÚst_datas rr zBmapCopy.__init__Ùsù€ðˆŒ à%)ˆÔ"Ø!ˆÔØ ˆÔØ'ˆÔØ !ˆÔà ˆÔØ"&ˆÔØ"&ˆÔ؈ŒØˆŒØˆŒØˆŒØ $ˆÔØˆÔØ!%ˆÔØ"ˆÔàˆŒ Ø ˆÔà!%ˆÔØ#ˆÔØ"ˆÔØ"ˆÔØ $ˆÔØ ×#Ñ# D¨$Ô/Ø!ˆÔàˆŒ Ø Ÿ:™:ˆÔàˆŒ ØŸ)™)ˆŒÜ—(‘(˜4Ÿ<™<×.Ñ.Ó0Ó1ˆÜ $§ ¡ ¨W¯_©_Ó =ˆÔðˆŒ ØˆŒ Ø#ˆÔØ$(ˆÔ!ô �L‰L˜Ÿ™Ô )Ü—‘˜Ÿ™Ó)¨QÒ.Ü—‘˜Ÿ™Ó)¨QÒ.à(-ˆDÕ %à(,ˆDÔ %á ØˆDŒLØ"Ÿi™iˆDŒOØ × Ñ Õ ð!"ˆDÔ Ø"ˆDŒOØ"%ˆDÔ á Ø × Ñ  Ô ,à!×.Ñ.°$·/±/ÑAˆÕrcóæ—tjj|«r:tjtj|«j «r||_ytjd|z«y)a÷ Set the psplash named pipe file path to be used when updating the progress - best effort. The 'path' argument is the named pipe used by the psplash process to get progress bar commands. When the path argument doesn't exist or is not a pipe, the function will ignore with a warning. This behavior is considered as such because the progress is considered a decoration functionality which might or might not be available even if requested. When used as a boot service, the unavailability of the psplash service (due to various reasons: no screen, racing issues etc.) should not break the writting process. This is why this implementation is done as a best effort. z;'%s' is not a pipe, so psplash progress will not be updatedN) rmrÚexistsrpÚS_ISFIFOrrrgr;Úwarning)rrs rÚset_psplash_pipezBmapCopy.set_psplash_pipe,sJ€ô �7‰7�>‰>˜$Ô ¤D§M¡M´"·'±'¸$³-×2GÑ2GÔ$HØ!%ˆDÕ ä �L‰LØPÐSWÑWõ rcó4—||_|r||_yd|_y)aÒ Setup the progress indicator which shows how much data has been copied in percent. The 'file_obj' argument is the console file object where the progress has to be printed to. Pass 'None' to disable the progress indicator. The 'format_string' argument is the format string for the progress indicator. It has to contain a single '%d' placeholder which will be substitutes with copied data in percent. z Copied %d%%N)rdre)rÚfile_objÚ format_strings rrfzBmapCopy.set_progress_indicatorCs€ð'ˆÔÙ Ø$1ˆDÕ !à$1ˆDÕ !rcóŽ—|j�4|j|k7r%td||j|jfz«‚||_t|«|_|j|jzdz |jz|_|j €4|j |_|j|_|j|_yy)zZ Set image size and initialize various other geometry-related attributes. NzBcannot set image size to %d bytes, it is known to be %d bytes (%s)r) rZr r[r rWrXrYr\r])rrZs rrzBmapCopy._set_image_sizeVs±€ð �?‰?Ð &¨4¯?©?¸jÒ+HÜð#à˜tŸ™°×0EÑ0EÐFñGóð ð %ˆŒÜ *¨:Ó 6ˆÔØŸ?™?¨T¯_©_Ñ<¸qÑ@ÀTÇ_Á_ÑTˆŒà �?‰?Ð "Ø"Ÿo™oˆDŒOØ#Ÿ™ˆDÔ Ø%)×%:Ñ%:ˆDÕ "ð #rc ód—ddl}|jj|j«jj «}|j|j j«d|j¬«}|j|j««}|dk7sJ‚d|jz||||jztj|j«}|j|«|j«}|j!«||k7rt#d|j$›d|›d|›d �«‚y) zR This is a helper function which verifies the bmap file checksum. rN)Úaccesséÿÿÿÿó0z!checksum mismatch for bmap file 'z': calculated 'z', should be 'r8)ÚmmaprNÚfindrwÚtextr(r_roÚ ACCESS_COPYÚencoderuÚhashlibÚnewrtÚupdateÚ hexdigestÚcloser r})rr‘Úcorrect_chksumÚ mapped_bmapÚ chksum_posÚhash_objÚcalculated_chksums rÚ_verify_bmap_checksumzBmapCopy._verify_bmap_checksumks€ó àŸ™Ÿ™¨×(AÑ(AÓB×GÑG×MÑMÓOˆð —i‘i § ¡ × 3Ñ 3Ó 5°qÀ×AQÑAQ�iÓRˆ à ×%Ñ% n×&;Ñ&;Ó&=Ó>ˆ ؘRÒÐÐà>BÀTÇ\Á\Ñ>Qˆ �J ¨d¯l©lÑ!:Ð;ä—;‘;˜tŸ}™}Ó-ˆØ�‰˜ Ô$Ø$×.Ñ.Ó0Ðà×ÑÔà  Ò .Ýð—?“?Ò$5²~ðGóð ð /rc ó — tj|j«|_|j}t|j«jjd ««|_t|jj!d d «d«|_t|jj!d d «d «|_|j"tt&j!d d «d«kDrtd t&|j"fz«‚t|j)d «j*j-««|_t|j)d«j*j-««|_t|j)d«j*j-««|_t|j)d«j*j-««|_t7|j4«|_|j2|j.z|_t7|j:«|_|j2dz|j0z |_|j4|j.zd z |j.z}|j0|k7r/td|j4|j0|j.fz«‚|j"d kDs|j"d k(rL|j$dk(r=|j)d«j*j-«|_ d|_!d|_"n$|j$dk(rd|_ d|_!d|_"|j@rM tGtIjJ|j@«jM««|_'|jS«yy#tj$r“}|jj d«d}t |j«D];\}}||jddz k\sŒ||jddzksŒ2|d||fzz }Œ=td|j›d|›d|›�«‚d}~wwxYw#tP$r }td|j@›d|›�«‚d}~wwxYw)z\ Parse the bmap file and initialize corresponding class instance attributs. rréz Line %d: %szcannot parse the bmap file 'z%' which should be a proper XML file: z, the XML extract: NÚversionÚ.rzKonly bmap format version up to %d is supported, version %d is not supportedÚ BlockSizeÚ BlocksCountÚMappedBlocksCountÚ ImageSizegY@z]Inconsistent bmap - image size does not match blocks count (%d bytes != %d blocks * %d bytes)Ú ChecksumTypeÚchksumÚBmapFileChecksumr#Úsha1Ú BmapFileSHA1z!cannot initialize hash function "z": )*rÚparser_rNÚ ParseErrorÚseekÚ enumerateÚpositionr r}rHÚgetrootÚattribÚgetrTÚintr-rUrVÚSUPPORTED_BMAP_VERSIONr’r“r(rWrXrYrZr r[r\r]r^rtrvrwÚlenr–r—r™ruÚ ValueErrorr )rÚerrÚ xml_extractÚnumÚlineÚxmlrXs rr~zBmapCopy._parse_bmap‹s·€ð  Ü#×)Ñ)¨$¯,©,Ó7ˆDŒIð�i‰iˆÜ § ¡ £ × 4Ñ 4× 8Ñ 8¸Ó CÓDˆÔô#& d×&7Ñ&7×&=Ñ&=¸cÀ1Ó&EÀaÑ&HÓ"IˆÔÜ"% d×&7Ñ&7×&=Ñ&=¸cÀ1Ó&EÀaÑ&HÓ"IˆÔØ × "Ñ "¤SÔ)?×)EÑ)EÀcÈ1Ó)MÈaÑ)PÓ%QÒ QÜð.ä)¨4×+BÑ+BÐCñDóð ô˜cŸh™h {Ó3×8Ñ8×>Ñ>Ó@ÓAˆŒÜ˜cŸh™h }Ó5×:Ñ:×@Ñ@ÓBÓCˆŒÜ˜cŸh™hÐ':Ó;×@Ñ@×FÑFÓHÓIˆŒÜ˜cŸh™h {Ó3×8Ñ8×>Ñ>Ó@ÓAˆŒÜ *¨4¯?©?Ó ;ˆÔØŸ?™?¨T¯_©_Ñ<ˆÔÜ!+¨D×,<Ñ,<Ó!=ˆÔØ#Ÿ™°Ñ6¸$¿/¹/ÑIˆÔà—o‘o¨¯©Ñ7¸!Ñ;ÀÇÁÑOˆ Ø �?‰?˜jÒ (ÜðBà—?‘? D§O¡O°T·_±_ÐEñFóð ð × "Ñ " QÒ &Ø × #Ñ # qÒ (¨T×-DÑ-DÈÒ-Ið  ŸH™H ^Ó4×9Ñ9×?Ñ?ÓAˆDŒMØ#+ˆDÔ Ø(:ˆDÕ %Ø × $Ñ $¨Ò )Ø"ˆDŒMØ#)ˆDÔ Ø(6ˆDÔ %à �=Š=ð Ü"¤7§;¡;¨t¯}©}Ó#=×#GÑ#GÓ#IÓJ�” ð × &Ñ &Õ (ð øôM×%Ñ%ò à �L‰L× Ñ ˜aÔ ØˆKÜ& t§|¡|Ö4‘ ��Tؘ#Ÿ,™, q™/¨AÑ-Ó-°#¸¿¹Àa¹È1Ñ9LÓ2LØ =°C¸°;Ñ#>Ñ>‘Kð5õð—?“?¢C©ð6óð ûð ûôRò ÝØBFÇ-Ã-ÑQTÐUóðûð ús<‚$N.Í!;QÎ.QÏA QÐQÐ%*QÑQÑ RÑ Q;Ñ;Rcób—|jr[||jksJ‚tt|«|jz dz«}tj d||j|fz«ntj d|z«|j �r|jrd|j zzdz}n}tjj«}tjd¬«}||jz |kry||_ d }d||jd zzdz}|xjd z c_ |jr|j jd «nd |_ |j j|«|j j«|jr�|jrt t j"t j$z}t!j&t!j(|j|«d«5}|jdz«ddd«yyy#1swYyxYw#YyxYw)zÊ Print the progress indicator if the mapped area size is known and if the indicator has been enabled by assigning a console file object to the 'progress_file' attribute. rMz wrote %d blocks out of %d (%d%%)zwrote %d blocksÚ Ú éú)Ú millisecondsN)Ú-Ú\Ú|Ú/r¢rzTr3z PROGRESS %d )rYr¶Úfloatr;r<rdreÚdatetimeÚnowÚ timedeltarcrbrar4ÚflushrgrmÚO_WRONLYÚ O_NONBLOCKÚfdopenr&) rÚblocks_writtenÚpercentÚprogressrÊÚ min_deltaÚprogress_wheelÚmodeÚp_fos rÚ_update_progresszBmapCopy._update_progressásÞ€ð �?Š?Ø! T§_¡_Ò4Ð 4Ð4Üœ5 Ó0°4·?±?ÑBÀcÑIÓJˆGÜ �J‰JØ2Ø! 4§?¡?°GÐ<ñ=õ ô �J‰JÐ(¨>Ñ9Ô :à × Ó Ø�ŠØ $×"7Ñ"7¸'Ñ"AÑAÀDÑH‘ô×'Ñ'×+Ñ+Ó-�Ü$×.Ñ.¸CÔ@� ؘ×,Ñ,Ñ,¨yÒ8ØØ&)�Ô#à!6�Ø .°×1EÑ1EÈÑ1IÑ"JÑJÈTÑQ�Ø×$Ò$¨Ñ)Õ$ð×%Ò%à×#Ñ#×)Ñ)¨)Õ4à)-�Ô&à × Ñ × %Ñ % hÔ /Ø × Ñ × %Ñ %Ô 'ð × Ò  $§/¢/ð Ü—{‘{¤R§]¡]Ñ2�Ü—Y‘YœrŸw™w t×'9Ñ'9¸4Ó@À#ÔFÈ$Ø—J‘J˜°Ñ8Ô9÷GÐFð#2Ð ÷GÐFûð Ùús+Æ)AH*Ç>HÈH*ÈH'È#H*È'H*È*H.c#ó¬K—|jsK|jrd|jdz df–—yd} |||jzdz df–—||jz }Œ'|j}|j d«}|j d«D]Ã}|j j«}|jdd«D�cgc]}|j«‘Œ}}t|d«}t|«dkDr!t|d«}||kDrtd|z«‚|}|j|jvr|j|j} nd} ||| f–—ŒÅycc}w­w)a] This is a helper generator that parses the bmap XML file and for each block range in the XML file it yields ('first', 'last', 'chksum') tuples, where: * 'first' is the first block of the range; * 'last' is the last block of the range; * 'chksum' is the checksum of the range ('None' is used if it is missing). If there is no bmap file, the generator just yields a single range for entire image file. If the image size is unknown, the generator infinitely yields continuous ranges of size '_batch_blocks'. rrNÚBlockMapÚRangerÄzbad range (first > last): '%s')r_rXrPrNr’Úfindallr“r(r-r¶r¸r rvr´) rÚfirstr¾Úxml_bmapÚ xml_elementÚ blocks_rangeÚxr-Úlastrªs rÚ_get_block_rangeszBmapCopy._get_block_rangess^èø€ð�|Š|à�ŠØ˜$Ÿ/™/¨AÑ-¨tÐ4Ò4ð ð �ØØ  %¨$×*<Ñ*<Ñ"<¸qÑ"@À$ÐGÒGؘT×/Ñ/Ñ/�Eðð �i‰iˆØ—8‘8˜JÓ'ˆà#×+Ñ+¨GÖ4ˆKØ&×+Ñ+×1Ñ1Ó3ˆLð)5×(:Ñ(:¸3ÀÔ(BÓCÑ(B 1�Q—W‘W•YÐ(BˆEÐC䘘a™“MˆEÜ�5‹z˜AŠ~ܘ5 ™8“}�ؘ4’<ÜÐ @À<Ñ OÓPÐPà�à×#Ñ# {×'9Ñ'9Ñ9Ø$×+Ñ+¨D×,@Ñ,@ÑA‘à�à˜$ Ð'Ó 'ñ)5ùò Dùs‚B7EÂ9EÃBEc#ó¦K—|j}||zdz |kr|||zdz |f–—||z }||zdz |krŒ||z dz}|r|||zdz |f–—yy­w)a™ This is a helper generator which splits block ranges from the bmap file to smaller batches. Indeed, we cannot read and write entire block ranges from the image file, because a range can be very large. So we perform the I/O in batches. Batch size is defined by the '_batch_blocks' attribute. Thus, for each (first, last) block range, the generator yields smaller (start, end, length) batch ranges, where: * 'start' is the starting batch block number; * 'last' is the ending batch block number; * 'length' is the batch length in blocks (same as 'end' - 'start' + 1). rN)rP)rrÜráÚ batch_blockss rÚ _get_batcheszBmapCopy._get_batchesPs‰èø€ð×)Ñ)ˆ à�lÑ" QÑ&¨$Ò.ؘ% ,Ñ.°Ñ2°LÐAÒ AØ �\Ñ !ˆEð�lÑ" QÑ&¨$Ó.ð˜e‘| aÑ'ˆ ٠ؘ% ,Ñ.°Ñ2°LÐAÓ Að ùs ‚5A¸Ac óΗtjd« |j«D�]´\}}}|r!|rtj|j «}|j j||jz«|j||«}|D�]\}}} |j j| |jz«} | s>tjd|j«|jjd«y|r|rj!| «t#| «|jzdz |jz} tjd| |jj%«fz«|jjd||| zdz | f«�Œ|s�Œs|s�Œwj'«|k7s�ŒŒtd|||j'«||jfz«‚ |jjd«y#t$r!} td|||j| fz«‚d} ~ wwxYw#t($r2|jjd t+j,«f«YŒƒwxYw) aB This is generator which reads the image file in '_batch_blocks' chunks and yields ('type', 'start', 'end', 'buf) tuples, where: * 'start' is the starting block number of the batch; * 'end' is the last block of the batch; * 'buf' a buffer containing the batch data. zthe reader thread has startedz;error while reading blocks %d-%d of the image file '%s': %sNz#no more data to read from file '%s'rz&queueing %d blocks, queue length is %dÚrangezUchecksum mismatch for blocks range %d-%d: calculated %s, should be %s (image file %s)r)r;r<râr–r—rtrhr°rWrår'r=r rjrQÚputr˜r¸Úqsizer™Ú ExceptionÚsysÚexc_info) rÚverifyrÜrárªržÚiteratorÚstartÚendÚlengthÚbufrºÚblockss rÚ _get_datazBmapCopy._get_datahs6€ô � ‰ Ð2Ô3ð/ =Ø)-×)?Ñ)?×)AÑ%�˜˜fÙ™fÜ&Ÿ{™{¨4¯=©=Ó9�Hà— ‘ ×"Ñ" 5¨4¯?©?Ñ#:Ô;à×,Ñ,¨U°DÓ9�Ü,4Ñ(�U˜C ðØ"Ÿm™m×0Ñ0°¸$¿/¹/Ñ1IÓJ˜ñÜŸ ™ ØAÀ4×CSÑCSôð×)Ñ)×-Ñ-¨dÔ3Úá¡&Ø Ÿ™¨Ô,ä! #›h¨¯©Ñ8¸1Ñ<ÀÇÁÑP�FÜ—J‘JØ@Ø! 4×#4Ñ#4×#:Ñ#:Ó#<Ð=ñ>ôð ×%Ñ%×)Ñ)¨7°E¸5À6¹>ÈAÑ;MÈsÐ*SÖTð3-5ó6›f¨×);Ñ);Ó)=ÀÔ)GÜðFà  $¨×(:Ñ(:Ó(<¸fÀd×FVÑFVÐWñXóðñG*Bð` ×Ñ×јdÕ#øôM#òÜ#ð2Ø5:¸CÀ×AQÑAQÐSVÐ4WñXóðûðûô@ò =ð × Ñ × !Ñ ! 7¬C¯L©L«NÐ";Ö <ð  =úsO—A?H)Â(G<Â??H)Ã?BH)ÆH)ÆH)Æ3,H)Ç< H&ÈH!È!H&È&H)È)8I$É#I$cóD—tj|j«|_tj|j |f«d}d}d}d|_d|_tjj«|_ |jrE|jr9 tj|jj!«|j« |jj)«}|€�n)|ddk(r|d}t+|d|d|d«|dd \} } } t-| «| | z dz|j.zksJ‚t-| «| | z |j.zkDsJ‚|jj1| |j.z«|j2r$|||j2zk\r|}|j5« |jj7| «|jj;«|| | z dzz }|t-| «z }|j=|«�ŒG|js|j?|«||j@k7r;t%d ||jB|j&|j@|jDfz«‚|jr9 tj|jj!«|j« |jjG«|r|j5«yy#t"$r }t%d|j&›d|›�«‚d}~wwxYw#t8$r!}t%d | | |j&|fz«‚d}~wwxYw#t"$r }t%d|j&›d|›�«‚d}~wwxYw#t8$r }t%d |j&›d|›�«‚d}~wwxYw) a Copy the image to the destination file using bmap. The 'sync' argument defines whether the destination file has to be synchronized upon return. The 'verify' argument defines whether the checksum has to be verified while copying. rFzcannot truncate file 'rANrrr%r¢z,error while writing blocks %d-%d of '%s': %szjwrote %u blocks from image '%s' to '%s', but should have %u - bmap file '%s' does not belong to this imagezcannot flush ')$ÚQueuerSrQÚthreadÚstart_new_threadrôrarbrÉrÊrcrZrsrmÚ ftruncaterkroÚOSErrorr rlrµrr¸rWr°rOÚsyncr4r=Ú task_doner×rrYrjr}rÌ) rrûrírÐÚ bytes_writtenÚ fsync_lastrºÚbatchrìrïrðròs rÚcopyz BmapCopy.copy¥sS€ô"ŸK™K¨×(=Ñ(=Ó>ˆÔÜ×Ñ §¡°° Ô:àˆØˆ ؈ à!&ˆÔØ ˆÔÜ&×/Ñ/×3Ñ3Ó5ˆÔà �?Š?˜t×4Ò4ð VÜ— ‘ ˜TŸ\™\×0Ñ0Ó2°D·O±OÔDð Ø×%Ñ%×)Ñ)Ó+ˆE؈}áØ�q‘˜WÒ$ð! ™8�ܘ ™  X¨a¡[°(¸1±+Ô>à % a¨  Ñ ˆU�C˜ä�s“8  e¡ ¨a¡°4·?±?ÑBÒBÐ BÐBÜ�s“8˜s U™{¨d¯o©oÑ=Ò=Ð =Ð=à �L‰L× Ñ ˜e d§o¡oÑ5Ô 6ð×)Ò)Ø! Z°$×2LÑ2LÑ%LÒLØ!/�JØ—I‘I”Kð Ø— ‘ ×"Ñ" 3Ô'ð × Ñ × 'Ñ 'Ô )Ø ˜c E™k¨A™oÑ -ˆNØ œS ›XÑ %ˆMà × !Ñ ! .Ô 1ñIðL�Šà × Ñ  Ô /ð ˜TŸ_™_Ò ,Üðð#Ø×$Ñ$Ø—O‘OØ—O‘OØ—O‘Oð ñ ó ð ð × Ò ð VÜ— ‘ ˜TŸ\™\×0Ñ0Ó2°D·O±OÔDð JØ �L‰L× Ñ Ô ñ Ø �I‰I�Kð øôWò Vݸt¿»ÑPSÐTÓUÐUûð Vûô>ò ÜØBؘc 4§?¡?°CÐ8ñ9óðûð ûôHò Vݸt¿»ÑPSÐTÓUÐUûð Vûô ò Jݰ4·?³?ÁCÐHÓIÐ Iûð Jús`Â8K1Æ5LÊ 8M ËM6Ë1 LË:LÌLÌ MÌ&MÍMÍ M3ÍM.Í.M3Í6 NÍ?NÎNcóê—|jr0 tj|jj ««fyy#t $r+}t d|j›d|j›d�«‚d}~wwxYw)zv Synchronize the destination file to make sure all the data are actually written to the disk. zcannot synchronize 'rAr$N) r|rmÚfsyncrkrorúr rlÚstrerror)rrºs rrûz BmapCopy.sync sb€ð × $Ò $ð Ü—‘˜Ÿ™×,Ñ,Ó.Ó/Ò0ð %øôò ÝØ6:·o³oÀsÇ|Ã|ÐTóðûð úsŽ.>¾ A2Á&A-Á-A2©NN©TT)r r rrr rˆrfrr r~r×rârårôrrûrrrrJrJ©sP„ñ-ó^QBòfò.2ò&;ò*ò@T)òl7òr4(òlBò0;$ózfóP rrJcó,‡—eZdZdZdd„Zdˆfd„ ZˆxZS)Ú BmapBdevCopya This class is a specialized version of 'BmapCopy' which copies the image to a block device. Unlike the base 'BmapCopy' class, this class does various optimizations specific to block devices, e.g., switching to the 'none' I/O scheduler. c óF—tj|||||«d|jz|_d|_d|_d|_|jrÉ tj|jj«dtj«}tj|jj«dtj«||jkr?td|j$›d|j&›d |j ›d t)|«›d � «‚tj*|jj««j,}d tj.|«›d tj0|«›d�|_tj2j5|jdz«s|jdz|_|jdz|_|jdz|_y#t$r+}td|j ›d|j"›d�«‚d}~wwxYw)z‹ The same as the constructor of the 'BmapCopy' base class, but adds useful guard-checks specific to block devices. i`Nrzcannot seed block device 'rAr$zthe image file 'z ' has size z' and it will not fit the block device 'z ' which has z capacityz/sys/dev/block/Ú:rÇrz../zqueue/schedulerz bdi/max_ratio)rJr rWrOÚ _sysfs_baseÚ_sysfs_scheduler_pathÚ_sysfs_max_ratio_pathrZrmÚlseekrkroÚSEEK_ENDÚSEEK_SETrúr rlrrjr[r rnrzryr{rr…)rr€r�r‚rZÚ bdev_sizerºrzs rr zBmapBdevCopy.__init__$s¦€ô ×ј$  t¨T°:Ô>à&5¸$¿/¹/Ñ%IˆÔ"àˆÔØ%)ˆÔ"Ø%)ˆÔ"ð �?Š?ð ÜŸH™H T§\¡\×%8Ñ%8Ó%:¸A¼r¿{¹{ÓK� Ü—‘˜Ÿ™×,Ñ,Ó.°´2·;±;Ô?ð˜4Ÿ?™?Ò*Ýð×(Ó(Ø×-Ó-ØŸ›Ü" 9Õ-ð ó ð ô—(‘(˜4Ÿ<™<×.Ñ.Ó0Ó1×9Ñ9‰ä �H‰H�WÕ Ü �H‰H�WÕ ð ˆÔô�w‰w�~‰~˜d×.Ñ.°Ñ8Ô9Ø#×/Ñ/°%Ñ7ˆDÔ à%)×%5Ñ%5Ð8IÑ%IˆÔ"Ø%)×%5Ñ%5¸Ñ%GˆÕ"øôAò Ýà—“¨¯ « ð6óðûð úsÁA:G,Ç, H Ç5&HÈH c ó>•—t|jd«5}t|jd«5}|jr#tj d|j›d�«|jrAtj d|j›d|jxsd›d|j›d�«|js |jr"tj d |j›�«t‰|�-||«d d d «d d d «y #1swYŒxYw#1swYy xYw) aÝ The same as in the base class but tunes the block device for better performance before starting writing. Additionally, it forces block device synchronization from time to time in order to make sure we do not get stuck in 'fsync()' for too long time. The problem is that the kernel synchronizes block devices when the file is closed. And the result is that if the user interrupts us while we are copying the data, the program will be blocked in 'close()' waiting for the block device synchronization, which may last minutes for slow USB stick. This is very bad user experience, and we work around this effect by synchronizing from time to time. Ú1Únonezsfailed to disable excessive buffering, expect worse system responsiveness (reason: cannot set max. I/O ratio to 1: Ú)zZfailed to enable I/O optimization, expect suboptimal speed (reason: cannot switch to the 'z' I/O scheduler: 'zunknown schedulerz ' in use. aSYou may want to set these I/O optimizations through a udev rule like this: #/etc/udev/rules.d/60-bmaptool-optimizations.rules SUBSYSTEM!="block", GOTO="bmaptool_optimizations_end" ACTION!="add|change", GOTO="bmaptool_optimizations_end" ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="xxxx", ATTRS{idProduct}=="xxxx", TAG+="uaccess" SUBSYSTEMS=="usb", ENV{DEVTYPE}!="partition", ATTRS{idVendor}=="xxxx", ATTRS{idProduct}=="xxxx", ATTR{bdi/min_ratio}="0", ATTR{bdi/max_ratio}="1", ATTR{queue/scheduler}="none" LABEL="bmaptool_optimizations_end" For attributes to match, try udevadm info -a N) rr r rr;r‡ÚinforrrlÚsuperr)rrûríÚ max_ratio_chgÚ scheduler_chgÚ __class__s €rrzBmapBdevCopy.copyZsø€ô0˜×3Ñ3°SÔ 9¸]ÌKØ × &Ñ &¨ôM à Ø×"Ò"Ü— ‘ ð,à,9×,?Ñ,?Ð+@ÀðCôð ×"Ò"Ü— ‘ ðà%×0Ñ0Ð1ð2Ø%×/Ñ/ÒFÐ3FÐGÀzØ$×*Ñ*Ð+¨1ð .ôð×"Ò" m×&9Ò&9Ü— ‘ ð'ð (,§¡Ð&7ð!9ôô( ‰G‰L˜˜vÔ &÷MM × 9Ð 9÷M ðM ú× 9Ð 9ús#˜D¯CDÃ6DÄD Ä DÄDrr)r r rrr rÚ __classcell__)rs@rrrsø„ñó4H÷l>'ñ>'rr)rrmrFrprër–ÚloggingrÉÚsixrÚ six.movesrrörr÷ÚtypingrÚ xml.etreerÚ BmapHelpersr Ú getLoggerr r;r·rêr rÚobjectrJrrrrÚr#s„ðñ" óT Û Û Û ÛÛÛÝÝ$Ý'ÝÝ!Ý#à€w×јÓ"€ðÐô ˆIô ÷MñMô`p ˆvôp ôf|'�8õ|'r