From ac7d017b91d00cb3013fb96c09c3d4b4e9ad0a86 Mon Sep 17 00:00:00 2001 From: Jason Frey Date: Wed, 3 Feb 2021 12:41:27 -0500 Subject: [PATCH] Extract WimParser to a dedicated gem --- lib/gems/pending/util/win32/wim_parser.rb | 120 ---------------------- manageiq-gems-pending.gemspec | 1 - spec/util/win32/data/tiny.wim | Bin 4048 -> 0 bytes spec/util/win32/wim_parser_spec.rb | 81 --------------- 4 files changed, 202 deletions(-) delete mode 100644 lib/gems/pending/util/win32/wim_parser.rb delete mode 100644 spec/util/win32/data/tiny.wim delete mode 100644 spec/util/win32/wim_parser_spec.rb diff --git a/lib/gems/pending/util/win32/wim_parser.rb b/lib/gems/pending/util/win32/wim_parser.rb deleted file mode 100644 index 02c1b6614..000000000 --- a/lib/gems/pending/util/win32/wim_parser.rb +++ /dev/null @@ -1,120 +0,0 @@ -# encoding: US-ASCII - -require "binary_struct" - -# Parser for the Windows Image Format (WIM). -# Information found here: -# http://www.microsoft.com/en-us/download/details.aspx?id=13096 -# http://technet.microsoft.com/en-us/library/cc749478%28WS.10%29.aspx?ITPID=win7dtp -# http://www.freepatentsonline.com/y2010/0211943.html -# http://nunobrito1981.blogspot.com/2010/12/inaccuracy-on-wim-documentation.html -# -# TODO: Add support for processing winnt.h GUID structures for wim_guid. -# http://msdn.microsoft.com/en-us/library/windows/desktop/aa373931%28v=vs.85%29.aspx -# http://stackoverflow.com/questions/679381/accessing-guid-members-in-c-sharp -class WimParser - autoload :NtUtil, "util/win32/nt_util" - autoload :Nokogiri, "nokogiri" - - HEADER_V1_STRUCT = BinaryStruct.new([ - 'a8', 'image_tag', # Signature that identifies the file as a .wim file. Value is set to "MSWIM\0\0". - 'L', 'size', # Size of the WIM header in bytes. - 'L', 'version', # The current version of the .wim file. This number will increase if the format of the .wim file changes. - 'L', 'flags', # Defines the custom flags (listed below). - 'L', 'compression_size', # Size of the compressed .wim file in bytes. - 'a16', 'wim_guid', # A unique identifier. - 'S', 'part_number', # The part number of the current .wim file in a spanned set. This value is 1, unless the data of the .wim file was split into multiple parts (.swm). - 'S', 'total_parts', # The total number of .wim file parts in a spanned set. - 'L', 'image_count', # The number of images contained in the .wim file. - 'L', 'offset_table_size', # The location of the resource lookup table. - 'L', 'offset_table_flags', - 'q', 'offset_table_offset', - 'q', 'offset_table_original_size', - 'L', 'xml_data_size', # The location of the XML data. - 'L', 'xml_data_flags', - 'q', 'xml_data_offset', - 'q', 'xml_data_original_size', - 'L', 'boot_metadata_size', # The location of the metadata resource. - 'L', 'boot_metadata_flags', - 'q', 'boot_metadata_offset', - 'q', 'boot_metadata_original_size', - 'L', 'boot_index', # The index of the bootable image in the .wim file. If this is zero, then there are no bootable images available. - 'L', 'integrity_size', # The location of integrity table used to verify files. - 'L', 'integrity_flags', - 'q', 'integrity_offset', - 'q', 'integrity_original_size', - 'a60', 'unused' # A reserved 60 bytes of additional space for future fields. - ]) - SIZEOF_HEADER_V1_STRUCT = HEADER_V1_STRUCT.size - - IMAGE_TAG = "MSWIM\0\0\0" - - # Flags values for the header struct - FLAG_HEADER_RESERVED = 0x00000001 - FLAG_HEADER_COMPRESSION = 0x00000002 # Resources within the WIM (both file and metadata) are compressed. - FLAG_HEADER_READONLY = 0x00000004 # The contents of this WIM should not be changed. - FLAG_HEADER_SPANNED = 0x00000008 # Resource data specified by the images within this WIM may be contained in another WIM. - FLAG_HEADER_RESOURCE_ONLY = 0x00000010 # This WIM contains file resources only. It does not contain any file metadata. - FLAG_HEADER_METADATA_ONLY = 0x00000020 # This WIM contains file metadata only. - FLAG_HEADER_WRITE_IN_PROGRESS = 0x00000040 # Limits one writer to the WIM file when opened with the WIM_FLAG_SHARE_WRITE mode, This flag is primarily used in the Windows Deployment Services (WDS) scenario. - FLAG_HEADER_RP_FIX = 0x00000080 # Reparse point fixup - # Additionally, if the FLAG_HEADER_COMPRESSION flag is set, the following flags are valid: - FLAG_HEADER_COMPRESS_RESERVED = 0x00010000 - FLAG_HEADER_COMPRESS_XPRESS = 0x00020000 # Resources within the wim are compressed using XPRESS compression. - FLAG_HEADER_COMPRESS_LZX = 0x00040000 # Resources within the wim are compressed using LZX compression. - - attr_reader :filename - - def initialize(filename) - @filename = filename - end - - def header - data = File.open(filename, "rb") do |f| - f.read(SIZEOF_HEADER_V1_STRUCT) - end - ret = HEADER_V1_STRUCT.decode(data) - raise "#{filename} is not a WIM file" if ret["image_tag"] != IMAGE_TAG - ret - end - - def xml_data - header_data = header - - xml = File.open(filename, "rb") do |f| - f.seek(header_data["xml_data_offset"]) - f.read(header_data["xml_data_size"]) - end - xml.force_encoding("UTF-16") - - xml = Nokogiri::XML(xml).xpath("/WIM") - - ret = {} - ret["total_bytes"] = xml.xpath("./TOTALBYTES").text.to_i - ret["images"] = xml.xpath("./IMAGE").collect do |i| - # Deal with hex time parts by removing the 0x prefix, padding with 0s to - # 8 characters, appending the low part to the high part, converting - # to an integer, and then converting that to a time object. - high_part = i.xpath("./CREATIONTIME/HIGHPART").text[2..-1].rjust(8, '0') - low_part = i.xpath("./CREATIONTIME/LOWPART").text[2..-1].rjust(8, '0') - creation_time = NtUtil.nt_filetime_to_ruby_time("#{high_part}#{low_part}".to_i(16)) - - high_part = i.xpath("./LASTMODIFICATIONTIME/HIGHPART").text[2..-1].rjust(8, '0') - low_part = i.xpath("./LASTMODIFICATIONTIME/LOWPART").text[2..-1].rjust(8, '0') - last_mod_time = NtUtil.nt_filetime_to_ruby_time("#{high_part}#{low_part}".to_i(16)) - - { - "index" => i["INDEX"].to_i, - "name" => i.xpath("./NAME").text, - "description" => i.xpath("./DESCRIPTION").text, - "dir_count" => i.xpath("./DIRCOUNT").text.to_i, - "file_count" => i.xpath("./FILECOUNT").text.to_i, - "total_bytes" => i.xpath("./TOTALBYTES").text.to_i, - "hard_link_bytes" => i.xpath("./HARDLINKBYTES").text.to_i, - "creation_time" => creation_time, - "last_modification_time" => last_mod_time, - } - end - ret - end -end diff --git a/manageiq-gems-pending.gemspec b/manageiq-gems-pending.gemspec index 9df7e3e1a..02bed16f7 100644 --- a/manageiq-gems-pending.gemspec +++ b/manageiq-gems-pending.gemspec @@ -23,7 +23,6 @@ Gem::Specification.new do |s| s.add_runtime_dependency "activesupport", "~> 6.0" s.add_runtime_dependency "awesome_spawn", "~> 1.5" s.add_runtime_dependency "aws-sdk-s3", "~> 1.0" - s.add_runtime_dependency "binary_struct", "~> 2.1" s.add_runtime_dependency "bundler", ">= 1.8.4" # rails-assets requires bundler >= 1.8.4, see: https://rails-assets.org/ s.add_runtime_dependency "erubis", "= 2.7.0" s.add_runtime_dependency "fog-openstack", "~> 0.3" diff --git a/spec/util/win32/data/tiny.wim b/spec/util/win32/data/tiny.wim deleted file mode 100644 index 87d3ff9f18fab3be3c86e647375a42245c40b363..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4048 zcmeHJdr(wW82@&c-Mwy*poj>LEHI*t3d_d&h(&>2Ky(2GjE6cdvOMG=2%(FZTmg44 zVj^h1!h)&kp^5n#L-P@dk_j@UnKddiDmfaNlT#+5edpXYQ&~p&!?DJ@d+#~l^L*cT z&;8CXA|@_80sz|Z20HLk-$2l2Ow-^_=$yv zED6sy^yB#!nkSy&Gup)EGU>ob%u=bu2&@^`=73>YOAI)2fV9NIV!_CAz~LWQOo<_B zSyH2;6bXwhgF=4FSvaUGL6iG7EHIpzir91%(MzJ|MCl%)ife7nwq*zAi&w4msan5%x?^NVWxeCMnt9a+ z6S?f5HvhoUEh`gbrXed5Oy`;m#$_9mzp`mp=@pj;7hJ17J85=6%%zjJj~45SK^$ME zaCX^PlGAVKf-lY&D1AOr&p0&u21`Yb3f$~`7y-Gbk&R0Vy>gv$L zzqJ)qyC;dYsCkQ?Gg8B3%rY9I($RRQK9nzS*_(zMV~fTJgD{hD%!y<~Y8XOuos9D^ zTwxkrgXF5fZLYvtXmG{x_)}Wy`M9PUBZ|T|^02K6J%?h9v2i|~mm^2?(@&L6r7cmo^0kg z#>g@zj*&{RnPNA?uFB9>$&l{KvN&g0DQ&zg3XEuAHZmOYu;-GSL4AhB34XsEZM=k{ z9hQzjy|J_lQ(Y=14VA+SSAbkSu_c#OPX}0pHbz{ZNJ!%~8>xHb(8kLYa9{>06K_JV zsKIiyozo?F2T%Cikf@i=lq8E1%Szq%iM+13dT^!O_g$&1vHT)qx=>{IvwQO9Aiw(h zR;8x3T#|nHW_C%3q}xXIlQJz-wR#8_@I#ccw5`F16>05j^>_DqZ9XU@v&zMKIz_K%%`ePXL9YDc--@j~V<;s=MUNLBh;vVcmBUX1Raz;C22Vx`dtd zJ~4E&j+r8Fb*nVxIqU5T3RdM@ANbiY*#B;0?V;uqvyOSnH&r#toDx%I_JhK=%-SiA zotBhQ?;(!JHI>&o4%o59uFgr((3pQvJ}E;Z7__WV`RN{YV|$T&v#oY``{*;F{mmsK zTkg!Bl|Cu(A&jESq(9sB_2Bpyvb)}t&KnU{9YV9)(OWDgaYi4!1{v zSmuf!^0PFqB?G0W%e*jE_U_pVf#TS8rFCO@$C;hho7@xs-1dyQ=&|Ax(ZvZR_ zfmAM}ApA1m(|`bK9)hbR1Y;?*R!;)Q@)3MxqrMzc(K-uf1c)V}H{K_SxGzxbZ%cpk A5&!@I diff --git a/spec/util/win32/wim_parser_spec.rb b/spec/util/win32/wim_parser_spec.rb deleted file mode 100644 index 85ab8f376..000000000 --- a/spec/util/win32/wim_parser_spec.rb +++ /dev/null @@ -1,81 +0,0 @@ -# encoding: US-ASCII - -require 'util/win32/wim_parser' -require 'time' - -describe WimParser do - WIM_PARSER_DATA_DIR = File.expand_path(File.join(File.dirname(__FILE__), 'data')) - - before(:each) do - @wim_parser = WimParser.new(File.join(WIM_PARSER_DATA_DIR, "tiny.wim")) - end - - context "#header" do - it "with a WIM file" do - expect(@wim_parser.header).to eq({ - "image_tag" => "MSWIM\0\0\0", - "size" => 208, - "version" => 68864, - "flags" => 0x00020082, - "compression_size" => 32768, - "wim_guid" => "N\x91-\xF7a'\x8D@\x9A0\xC5\xF1~\xD7X\x16", # real GUID is pending adding support for winnt.h GUID structure parsing - "part_number" => 1, - "total_parts" => 1, - "image_count" => 2, - "offset_table_size" => 150, - "offset_table_flags" => 0x02000000, - "offset_table_offset" => 2254, - "offset_table_original_size" => 150, - "xml_data_size" => 1644, - "xml_data_flags" => 0x02000000, - "xml_data_offset" => 2404, - "xml_data_original_size" => 1644, - "boot_metadata_size" => 0, - "boot_metadata_flags" => 0x00000000, - "boot_metadata_offset" => 0, - "boot_metadata_original_size" => 0, - "boot_index" => 0, - "integrity_size" => 0, - "integrity_flags" => 0x00000000, - "integrity_offset" => 0, - "integrity_original_size" => 0, - "unused" => ("\0" * 60), - }) - end - - it "with a non-WIM file" do - w = WimParser.new(__FILE__) - expect { w.header }.to raise_error(RuntimeError, /is not a WIM file/) - end - end - - it "#xml_data" do - expect(@wim_parser.xml_data).to eq({ - "total_bytes" => 2404, - "images" => [ - { - "index" => 1, - "name" => "Nothing", - "description" => "Empty Windows Disk", - "dir_count" => 3, - "file_count" => 0, - "total_bytes" => 0, - "hard_link_bytes" => 0, - "creation_time" => Time.parse("2012-09-01 04:05:53 UTC"), - "last_modification_time" => Time.parse("2012-09-01 04:05:53 UTC"), - }, - { - "index" => 2, - "name" => "appended image", - "description" => "some files added", - "dir_count" => 5, - "file_count" => 1, - "total_bytes" => 4, - "hard_link_bytes" => 0, - "creation_time" => Time.parse("2012-09-01 04:08:59 UTC"), - "last_modification_time" => Time.parse("2012-09-01 04:08:59 UTC"), - }, - ] - }) - end -end