class Zip::FileSystem::ZipFsFile

similarity with the methods in File
The individual methods are not documented due to their
builtin File (class) object, except it works on Zip::File entries.
Zip::File::file. An instance of ZipFsFile behaves like ruby’s
Instances of this class are normally accessed via the accessor

def atime(filename)

def atime(filename)
  e = get_entry(filename)
  if e.extra.member? 'UniversalTime'
    e.extra['UniversalTime'].atime
  elsif e.extra.member? 'NTFS'
    e.extra['NTFS'].atime
  end
end

def basename(filename)

def basename(filename)
  ::File.basename(filename)
end

def blockdev?(_filename)

def blockdev?(_filename)
  false
end

def chardev?(_filename)

def chardev?(_filename)
  false
end

def chmod(mode, *filenames)

def chmod(mode, *filenames)
  filenames.each do |filename|
    e = get_entry(filename)
    e.fstype = 3 # force convertion filesystem type to unix
    e.unix_perms = mode
    e.external_file_attributes = mode << 16
    e.dirty = true
  end
  filenames.size
end

def chown(owner, group, *filenames)

def chown(owner, group, *filenames)
  filenames.each do |filename|
    e = get_entry(filename)
    e.extra.create('IUnix') unless e.extra.member?('IUnix')
    e.extra['IUnix'].uid = owner
    e.extra['IUnix'].gid = group
  end
  filenames.size
end

def ctime(filename)

def ctime(filename)
  e = get_entry(filename)
  if e.extra.member? 'UniversalTime'
    e.extra['UniversalTime'].ctime
  elsif e.extra.member? 'NTFS'
    e.extra['NTFS'].ctime
  end
end

def delete(*args)

def delete(*args)
  args.each do |filename|
    if directory?(filename)
      raise Errno::EISDIR, "Is a directory - \"#{filename}\""
    end
    @mapped_zip.remove(filename)
  end
end

def directory?(filename)

def directory?(filename)
  entry = @mapped_zip.find_entry(filename)
  expand_path(filename) == '/' || (!entry.nil? && entry.directory?)
end

def dirname(filename)

def dirname(filename)
  ::File.dirname(filename)
end

def executable?(filename)

def executable?(filename)
  unix_mode_cmp(filename, 0o111)
end

def exists?(filename)

def exists?(filename)
  expand_path(filename) == '/' || !@mapped_zip.find_entry(filename).nil?
end

def expand_path(path)

def expand_path(path)
  @mapped_zip.expand_path(path)
end

def file?(filename)

def file?(filename)
  entry = @mapped_zip.find_entry(filename)
  !entry.nil? && entry.file?
end

def foreach(filename, sep = $INPUT_RECORD_SEPARATOR, &a_proc)

def foreach(filename, sep = $INPUT_RECORD_SEPARATOR, &a_proc)
  self.open(filename) { |is| is.each_line(sep, &a_proc) }
end

def ftype(filename)

def ftype(filename)
  @mapped_zip.get_entry(filename).directory? ? 'directory' : 'file'
end

def get_entry(filename)

def get_entry(filename)
  unless exists?(filename)
    raise Errno::ENOENT, "No such file or directory - #{filename}"
  end
  @mapped_zip.find_entry(filename)
end

def initialize(mapped_zip)

def initialize(mapped_zip)
  @mapped_zip = mapped_zip
end

def join(*fragments)

def join(*fragments)
  ::File.join(*fragments)
end

def link(_filename, _symlink_name)

def link(_filename, _symlink_name)
  raise NotImplementedError, 'The link() function is not implemented'
end

def mtime(filename)

def mtime(filename)
  @mapped_zip.get_entry(filename).mtime
end

def new(filename, mode = 'r')

def new(filename, mode = 'r')
  self.open(filename, mode)
end

def open(filename, mode = 'r', permissions = 0o644, &block)

def open(filename, mode = 'r', permissions = 0o644, &block)
  mode.delete!('b') # ignore b option
  case mode
  when 'r'
    @mapped_zip.get_input_stream(filename, &block)
  when 'w'
    @mapped_zip.get_output_stream(filename, permissions, &block)
  else
    raise StandardError, "openmode '#{mode} not supported" unless mode == 'r'
  end
end

def pipe

def pipe
  raise NotImplementedError, 'The pipe() function is not implemented'
end

def pipe?(_filename)

def pipe?(_filename)
  false
end

def popen(*args, &a_proc)

def popen(*args, &a_proc)
  ::File.popen(*args, &a_proc)
end

def read(filename)

def read(filename)
  @mapped_zip.read(filename)
end

def readable?(filename)

def readable?(filename)
  unix_mode_cmp(filename, 0o444)
end

def readlines(filename)

def readlines(filename)
  self.open(filename, &:readlines)
end

def readlink(_filename)

def readlink(_filename)
  raise NotImplementedError, 'The readlink() function is not implemented'
end

def rename(file_to_rename, new_name)

def rename(file_to_rename, new_name)
  @mapped_zip.rename(file_to_rename, new_name) { true }
end

def setgid?(filename)

def setgid?(filename)
  unix_mode_cmp(filename, 0o2000)
end

def setuid?(filename)

def setuid?(filename)
  unix_mode_cmp(filename, 0o4000)
end

def size(filename)

def size(filename)
  @mapped_zip.get_entry(filename).size
end

def size?(filename)

Returns nil for not found and nil for directories
def size?(filename)
  entry = @mapped_zip.find_entry(filename)
  entry.nil? || entry.directory? ? nil : entry.size
end

def socket?(_filename)

def socket?(_filename)
  false
end

def split(filename)

def split(filename)
  ::File.split(filename)
end

def stat(filename)

def stat(filename)
  raise Errno::ENOENT, filename unless exists?(filename)
  ZipFsStat.new(self, filename)
end

def sticky?(filename)

def sticky?(filename)
  unix_mode_cmp(filename, 0o1000)
end

def symlink(_filename, _symlink_name)

def symlink(_filename, _symlink_name)
  raise NotImplementedError, 'The symlink() function is not implemented'
end

def symlink?(_filename)

def symlink?(_filename)
  false
end

def truncate(_filename, _len)

def truncate(_filename, _len)
  raise StandardError, 'truncate not supported'
end

def umask(*args)

def umask(*args)
  ::File.umask(*args)
end

def unix_mode_cmp(filename, mode)

def unix_mode_cmp(filename, mode)
  e = get_entry(filename)
  e.fstype == 3 && ((e.external_file_attributes >> 16) & mode) != 0
rescue Errno::ENOENT
  false
end

def utime(modified_time, *filenames)

def utime(modified_time, *filenames)
  filenames.each do |filename|
    get_entry(filename).time = modified_time
  end
end

def writable?(filename)

def writable?(filename)
  unix_mode_cmp(filename, 0o222)
end

def zero?(filename)

def zero?(filename)
  sz = size(filename)
  sz.nil? || sz == 0
rescue Errno::ENOENT
  false
end