module Zip class CentralDirectory include Enumerable END_OF_CDS = 0x06054b50 ZIP64_END_OF_CDS = 0x06064b50 ZIP64_EOCD_LOCATOR = 0x07064b50 MAX_END_OF_CDS_SIZE = 65536 + 18 STATIC_EOCD_SIZE = 22 attr_reader :comment # Returns an Enumerable containing the entries. def entries @entry_set.entries end def initialize(entries = EntrySet.new, comment = '') #:nodoc: super() @entry_set = entries.kind_of?(EntrySet) ? entries : EntrySet.new(entries) @comment = comment end def write_to_stream(io) #:nodoc: cdir_offset = io.tell @entry_set.each { |entry| entry.write_c_dir_entry(io) } eocd_offset = io.tell cdir_size = eocd_offset - cdir_offset if ::Zip.write_zip64_support need_zip64_eocd = cdir_offset > 0xFFFFFFFF || cdir_size > 0xFFFFFFFF || @entry_set.size > 0xFFFF need_zip64_eocd ||= @entry_set.any? { |entry| entry.extra['Zip64'] } if need_zip64_eocd write_64_e_o_c_d(io, cdir_offset, cdir_size) write_64_eocd_locator(io, eocd_offset) end end write_e_o_c_d(io, cdir_offset, cdir_size) end def write_e_o_c_d(io, offset, cdir_size) #:nodoc: tmp = [ END_OF_CDS, 0, # @numberOfThisDisk 0, # @numberOfDiskWithStartOfCDir @entry_set ? [@entry_set.size, 0xFFFF].min : 0, @entry_set ? [@entry_set.size, 0xFFFF].min : 0, [cdir_size, 0xFFFFFFFF].min, [offset, 0xFFFFFFFF].min, @comment ? @comment.bytesize : 0 ] io << tmp.pack('VvvvvVVv') io << @comment end private :write_e_o_c_d def write_64_e_o_c_d(io, offset, cdir_size) #:nodoc: tmp = [ ZIP64_END_OF_CDS, 44, # size of zip64 end of central directory record (excludes signature and field itself) VERSION_MADE_BY, VERSION_NEEDED_TO_EXTRACT_ZIP64, 0, # @numberOfThisDisk 0, # @numberOfDiskWithStartOfCDir @entry_set ? @entry_set.size : 0, # number of entries on this disk @entry_set ? @entry_set.size : 0, # number of entries total cdir_size, # size of central directory offset, # offset of start of central directory in its disk ] io << tmp.pack('VQ