lib/archive/zip.rb
def find_central_directory(io)
      # First find the offset to the end of central directory record.
      # It is expected that the variable length comment field will usually be
      # empty and as a result the initial value of eocd_offset is all that is
      # necessary.
      #
      # NOTE: A cleverly crafted comment could throw this thing off if the
      # comment itself looks like a valid end of central directory record.
      eocd_offset = -22
      loop do
        io.seek(eocd_offset, IO::SEEK_END)
        if IOExtensions.read_exactly(io, 4) == EOCD_SIGNATURE then
          io.seek(16, IO::SEEK_CUR)
          if IOExtensions.read_exactly(io, 2).unpack('v')[0] ==
               (eocd_offset + 22).abs then
            break
          end
        end
        eocd_offset -= 1
      end
      # At this point, eocd_offset should point to the location of the end of
      # central directory record relative to the end of the archive.
      # Now, jump into the location in the record which contains a pointer to
      # the start of the central directory record and return the value.
      io.seek(eocd_offset + 16, IO::SEEK_END)
      return IOExtensions.read_exactly(io, 4).unpack('V')[0]
    rescue Errno::EINVAL
      raise Zip::UnzipError, 'unable to locate end-of-central-directory record'
    end
def find_central_directory(io)
      # First find the offset to the end of central directory record.
      # It is expected that the variable length comment field will usually be
      # empty and as a result the initial value of eocd_offset is all that is
      # necessary.
      #
      # NOTE: A cleverly crafted comment could throw this thing off if the
      # comment itself looks like a valid end of central directory record.
      eocd_offset = -22
      loop do
        io.seek(eocd_offset, IO::SEEK_END)
        if IOExtensions.read_exactly(io, 4) == EOCD_SIGNATURE then
          io.seek(16, IO::SEEK_CUR)
          if IOExtensions.read_exactly(io, 2).unpack('v')[0] ==
               (eocd_offset + 22).abs then
            break
          end
        end
        eocd_offset -= 1
      end
      # At this point, eocd_offset should point to the location of the end of
      # central directory record relative to the end of the archive.
      # Now, jump into the location in the record which contains a pointer to
      # the start of the central directory record and return the value.
      io.seek(eocd_offset + 16, IO::SEEK_END)
      return IOExtensions.read_exactly(io, 4).unpack('V')[0]
    rescue Errno::EINVAL
      raise Zip::UnzipError, 'unable to locate end-of-central-directory record'
    end
Returns the file offset of the first record in the central directory.
 _io_ must be a seekable, readable, IO-like object.

 Raises Archive::Zip::UnzipError if the end of central directory signature
 is not found where expected or at all.