class CPIO::ASCIIReader
Constants
- FIELD_ORDER
- FIELD_SIZES
- HEADER_LENGTH
- HEADER_PACK
Public Class Methods
new(io)
click to toggle source
# File lib/excavate/extractors/cpio/cpio.rb, line 71 def initialize(io) @io = io end
Public Instance Methods
each(&block)
click to toggle source
# File lib/excavate/extractors/cpio/cpio.rb, line 81 def each(&block) while true entry = read break if entry.nil? # The CPIO format has the end-of-stream marker as a file called "TRAILER!!!" break if entry.name == "TRAILER!!!" block.call(entry, entry.file) verify_correct_read(entry) unless entry.directory? end end
Private Instance Methods
io()
click to toggle source
# File lib/excavate/extractors/cpio/cpio.rb, line 77 def io @io end
padding_file(entry)
click to toggle source
# File lib/excavate/extractors/cpio/cpio.rb, line 158 def padding_file(entry) (-(HEADER_LENGTH + entry.filesize + 2) % 4) end
padding_name(entry)
click to toggle source
# File lib/excavate/extractors/cpio/cpio.rb, line 153 def padding_name(entry) # name padding is padding up to a multiple of 4 after header+namesize -(HEADER_LENGTH + entry.namesize) % 4 end
read()
click to toggle source
# File lib/excavate/extractors/cpio/cpio.rb, line 108 def read entry = CPIOEntry.new header = io.read(HEADER_LENGTH) return nil if header.nil? FIELD_ORDER.zip(header.unpack(HEADER_PACK)).each do |field, value| entry.send("#{field}=", value.to_i(16)) end entry.validate entry.mtime = Time.at(entry.mtime) read_name(entry, @io) read_file(entry, @io) entry end
read_file(entry, io)
click to toggle source
# File lib/excavate/extractors/cpio/cpio.rb, line 134 def read_file(entry, io) if entry.directory? entry.file = nil #read_file_padding(entry, io) nil else entry.file = BoundedIO.new(io, entry.filesize) do read_file_padding(entry, io) end end end
read_file_padding(entry, io)
click to toggle source
# File lib/excavate/extractors/cpio/cpio.rb, line 146 def read_file_padding(entry, io) padding_data = io.read(padding_file(entry)) if padding_data != ("\0" * padding_data.bytesize) raise ArgumentError, "Corrupt CPIO or bug? File null padding was #{padding_file(entry)} bytes: #{padding_data.inspect}" end end
read_name(entry, io)
click to toggle source
# File lib/excavate/extractors/cpio/cpio.rb, line 123 def read_name(entry, io) entry.name = io.read(entry.namesize - 1) # - 1 for null terminator nul = io.read(1) raise ArgumentError, "Corrupt CPIO or bug? Name null terminator was not null: #{nul.inspect}" if nul != "\0" padding_data = io.read(padding_name(entry)) # Padding should be all null bytes if padding_data != ("\0" * padding_data.bytesize) raise ArgumentError, "Corrupt CPIO or bug? Name null padding was #{padding_name(entry)} bytes: #{padding_data.inspect}" end end
verify_correct_read(entry)
click to toggle source
# File lib/excavate/extractors/cpio/cpio.rb, line 92 def verify_correct_read(entry) # Read and throw away the whole file if not read at all. entry.file.tap do |file| if file.nil? || file.remaining == 0 # All OK! :) elsif file.remaining == file.length file.read(16384) while !file.eof? else # The file was only partially read? This should be an error by the # user. consumed = file.length - file.remaining raise BadState, "Only #{consumed} bytes were read of the #{file.length} byte file: #{entry.name}" end end end