2013-06-03 15:56:24 +08:00
|
|
|
require 'zip'
|
2002-07-27 04:58:51 +08:00
|
|
|
|
2002-07-27 06:20:25 +08:00
|
|
|
module Zip
|
2015-03-21 03:43:29 +08:00
|
|
|
# The ZipFileSystem API provides an API for accessing entries in
|
|
|
|
# a zip archive that is similar to ruby's builtin File and Dir
|
2005-02-18 04:27:02 +08:00
|
|
|
# classes.
|
|
|
|
#
|
2013-09-25 17:40:35 +08:00
|
|
|
# Requiring 'zip/filesystem' includes this module in Zip::File
|
|
|
|
# making the methods in this module available on Zip::File objects.
|
2005-02-18 04:27:02 +08:00
|
|
|
#
|
2015-03-21 03:43:29 +08:00
|
|
|
# Using this API the following example creates a new zip file
|
2005-02-18 04:27:02 +08:00
|
|
|
# <code>my.zip</code> containing a normal entry with the name
|
|
|
|
# <code>first.txt</code>, a directory entry named <code>mydir</code>
|
|
|
|
# and finally another normal entry named <code>second.txt</code>
|
|
|
|
#
|
2013-06-03 15:56:24 +08:00
|
|
|
# require 'zip/filesystem'
|
2015-03-21 03:43:29 +08:00
|
|
|
#
|
2013-09-25 17:40:35 +08:00
|
|
|
# Zip::File.open("my.zip", Zip::File::CREATE) {
|
2005-02-18 04:27:02 +08:00
|
|
|
# |zipfile|
|
|
|
|
# zipfile.file.open("first.txt", "w") { |f| f.puts "Hello world" }
|
|
|
|
# zipfile.dir.mkdir("mydir")
|
|
|
|
# zipfile.file.open("mydir/second.txt", "w") { |f| f.puts "Hello again" }
|
|
|
|
# }
|
|
|
|
#
|
2015-03-21 03:43:29 +08:00
|
|
|
# Reading is as easy as writing, as the following example shows. The
|
2005-02-18 04:27:02 +08:00
|
|
|
# example writes the contents of <code>first.txt</code> from zip archive
|
|
|
|
# <code>my.zip</code> to standard out.
|
|
|
|
#
|
2013-06-03 15:56:24 +08:00
|
|
|
# require 'zip/filesystem'
|
2015-03-21 03:43:29 +08:00
|
|
|
#
|
2013-06-03 15:56:24 +08:00
|
|
|
# Zip::File.open("my.zip") {
|
2005-02-18 04:27:02 +08:00
|
|
|
# |zipfile|
|
|
|
|
# puts zipfile.file.read("first.txt")
|
|
|
|
# }
|
|
|
|
|
2013-06-03 15:56:24 +08:00
|
|
|
module FileSystem
|
2005-02-18 04:27:02 +08:00
|
|
|
def initialize # :nodoc:
|
2003-08-20 23:30:03 +08:00
|
|
|
mappedZip = ZipFileNameMapper.new(self)
|
|
|
|
@zipFsDir = ZipFsDir.new(mappedZip)
|
|
|
|
@zipFsFile = ZipFsFile.new(mappedZip)
|
2003-08-20 22:10:20 +08:00
|
|
|
@zipFsDir.file = @zipFsFile
|
|
|
|
@zipFsFile.dir = @zipFsDir
|
|
|
|
end
|
|
|
|
|
2005-02-18 04:27:02 +08:00
|
|
|
# Returns a ZipFsDir which is much like ruby's builtin Dir (class)
|
2013-09-25 17:40:35 +08:00
|
|
|
# object, except it works on the Zip::File on which this method is
|
2005-02-18 04:27:02 +08:00
|
|
|
# invoked
|
2002-07-27 06:20:25 +08:00
|
|
|
def dir
|
2003-08-20 22:10:20 +08:00
|
|
|
@zipFsDir
|
2002-07-27 06:20:25 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2005-02-18 04:27:02 +08:00
|
|
|
# Returns a ZipFsFile which is much like ruby's builtin File (class)
|
2013-09-25 17:40:35 +08:00
|
|
|
# object, except it works on the Zip::File on which this method is
|
2005-02-18 04:27:02 +08:00
|
|
|
# invoked
|
2002-07-27 06:20:25 +08:00
|
|
|
def file
|
2003-08-20 22:10:20 +08:00
|
|
|
@zipFsFile
|
2002-07-27 06:20:25 +08:00
|
|
|
end
|
2005-02-18 04:27:02 +08:00
|
|
|
|
|
|
|
# Instances of this class are normally accessed via the accessor
|
2013-09-25 17:40:35 +08:00
|
|
|
# Zip::File::file. An instance of ZipFsFile behaves like ruby's
|
|
|
|
# builtin File (class) object, except it works on Zip::File entries.
|
2005-02-18 04:27:02 +08:00
|
|
|
#
|
|
|
|
# The individual methods are not documented due to their
|
|
|
|
# similarity with the methods in File
|
2002-07-27 06:20:25 +08:00
|
|
|
class ZipFsFile
|
2003-08-20 22:10:20 +08:00
|
|
|
attr_writer :dir
|
2015-03-25 00:31:28 +08:00
|
|
|
# protected :dir
|
2003-08-20 22:10:20 +08:00
|
|
|
|
2003-08-13 16:39:01 +08:00
|
|
|
class ZipFsStat
|
2012-02-01 17:47:17 +08:00
|
|
|
class << self
|
|
|
|
def delegate_to_fs_file(*methods)
|
|
|
|
methods.each do |method|
|
2015-03-23 00:30:24 +08:00
|
|
|
class_eval <<-end_eval, __FILE__, __LINE__ + 1
|
2012-02-01 17:47:17 +08:00
|
|
|
def #{method} # def file?
|
|
|
|
@zipFsFile.#{method}(@entryName) # @zipFsFile.file?(@entryName)
|
|
|
|
end # end
|
|
|
|
end_eval
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2003-08-13 16:39:01 +08:00
|
|
|
def initialize(zipFsFile, entryName)
|
|
|
|
@zipFsFile = zipFsFile
|
|
|
|
@entryName = entryName
|
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2003-08-13 21:18:25 +08:00
|
|
|
def kind_of?(t)
|
2015-03-21 03:43:29 +08:00
|
|
|
super || t == ::File::Stat
|
2003-08-13 21:18:25 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2012-02-01 17:47:17 +08:00
|
|
|
delegate_to_fs_file :file?, :directory?, :pipe?, :chardev?, :symlink?,
|
2015-03-21 15:44:56 +08:00
|
|
|
:socket?, :blockdev?, :readable?, :readable_real?, :writable?, :ctime,
|
|
|
|
:writable_real?, :executable?, :executable_real?, :sticky?, :owned?,
|
|
|
|
:grpowned?, :setuid?, :setgid?, :zero?, :size, :size?, :mtime, :atime
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2015-03-23 00:37:59 +08:00
|
|
|
def blocks
|
|
|
|
nil
|
|
|
|
end
|
2003-08-13 21:18:25 +08:00
|
|
|
|
2004-01-30 23:07:56 +08:00
|
|
|
def get_entry
|
|
|
|
@zipFsFile.__send__(:get_entry, @entryName)
|
|
|
|
end
|
|
|
|
private :get_entry
|
|
|
|
|
|
|
|
def gid
|
|
|
|
e = get_entry
|
2015-03-21 16:27:44 +08:00
|
|
|
if e.extra.member? 'IUnix'
|
|
|
|
e.extra['IUnix'].gid || 0
|
2004-01-30 23:07:56 +08:00
|
|
|
else
|
|
|
|
0
|
|
|
|
end
|
|
|
|
end
|
2003-08-13 21:18:25 +08:00
|
|
|
|
2004-01-30 23:07:56 +08:00
|
|
|
def uid
|
|
|
|
e = get_entry
|
2015-03-21 16:27:44 +08:00
|
|
|
if e.extra.member? 'IUnix'
|
|
|
|
e.extra['IUnix'].uid || 0
|
2004-01-30 23:07:56 +08:00
|
|
|
else
|
|
|
|
0
|
|
|
|
end
|
|
|
|
end
|
2003-08-13 21:18:25 +08:00
|
|
|
|
2015-03-23 00:37:59 +08:00
|
|
|
def ino
|
|
|
|
0
|
|
|
|
end
|
2003-08-13 21:18:25 +08:00
|
|
|
|
2015-03-23 00:37:59 +08:00
|
|
|
def dev
|
|
|
|
0
|
|
|
|
end
|
2003-08-13 16:39:01 +08:00
|
|
|
|
2015-03-23 00:37:59 +08:00
|
|
|
def rdev
|
|
|
|
0
|
|
|
|
end
|
2003-08-13 21:18:25 +08:00
|
|
|
|
2015-03-23 00:37:59 +08:00
|
|
|
def rdev_major
|
|
|
|
0
|
|
|
|
end
|
2003-08-13 21:18:25 +08:00
|
|
|
|
2015-03-23 00:37:59 +08:00
|
|
|
def rdev_minor
|
|
|
|
0
|
|
|
|
end
|
2003-08-13 21:18:25 +08:00
|
|
|
|
|
|
|
def ftype
|
|
|
|
if file?
|
2015-03-21 16:27:44 +08:00
|
|
|
return 'file'
|
2003-08-13 21:18:25 +08:00
|
|
|
elsif directory?
|
2015-03-21 16:27:44 +08:00
|
|
|
return 'directory'
|
2003-08-13 21:18:25 +08:00
|
|
|
else
|
2015-03-21 16:27:44 +08:00
|
|
|
raise StandardError, 'Unknown file type'
|
2003-08-13 21:18:25 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-03-23 00:37:59 +08:00
|
|
|
def nlink
|
|
|
|
1
|
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2015-03-23 00:37:59 +08:00
|
|
|
def blksize
|
|
|
|
nil
|
|
|
|
end
|
2003-08-19 20:33:23 +08:00
|
|
|
|
2004-01-30 23:07:56 +08:00
|
|
|
def mode
|
|
|
|
e = get_entry
|
|
|
|
if e.fstype == 3
|
2013-06-03 02:33:03 +08:00
|
|
|
e.external_file_attributes >> 16
|
2004-01-30 23:07:56 +08:00
|
|
|
else
|
2015-03-24 00:23:04 +08:00
|
|
|
33_206 # 33206 is equivalent to -rw-rw-rw-
|
2004-01-30 23:07:56 +08:00
|
|
|
end
|
|
|
|
end
|
2003-08-13 16:39:01 +08:00
|
|
|
end
|
|
|
|
|
2003-08-20 23:30:03 +08:00
|
|
|
def initialize(mappedZip)
|
2011-11-16 23:04:28 +08:00
|
|
|
@mappedZip = mappedZip
|
2002-07-27 06:20:25 +08:00
|
|
|
end
|
2004-01-30 23:07:56 +08:00
|
|
|
|
|
|
|
def get_entry(fileName)
|
2015-03-24 00:11:32 +08:00
|
|
|
unless exists?(fileName)
|
2004-01-30 23:07:56 +08:00
|
|
|
raise Errno::ENOENT, "No such file or directory - #{fileName}"
|
|
|
|
end
|
|
|
|
@mappedZip.find_entry(fileName)
|
|
|
|
end
|
|
|
|
private :get_entry
|
|
|
|
|
|
|
|
def unix_mode_cmp(fileName, mode)
|
2015-03-23 00:33:44 +08:00
|
|
|
e = get_entry(fileName)
|
2015-03-23 00:56:37 +08:00
|
|
|
e.fstype == 3 && ((e.external_file_attributes >> 16) & mode) != 0
|
2015-03-23 00:33:44 +08:00
|
|
|
rescue Errno::ENOENT
|
|
|
|
false
|
2004-01-30 23:07:56 +08:00
|
|
|
end
|
|
|
|
private :unix_mode_cmp
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2002-07-27 06:20:25 +08:00
|
|
|
def exists?(fileName)
|
2015-06-08 15:29:08 +08:00
|
|
|
expand_path(fileName) == '/' || !@mappedZip.find_entry(fileName).nil?
|
2002-07-27 06:20:25 +08:00
|
|
|
end
|
2015-03-21 18:14:21 +08:00
|
|
|
alias exist? exists?
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2003-08-13 15:51:42 +08:00
|
|
|
# Permissions not implemented, so if the file exists it is accessible
|
2015-03-21 18:14:21 +08:00
|
|
|
alias owned? exists?
|
|
|
|
alias grpowned? exists?
|
2003-08-13 17:44:47 +08:00
|
|
|
|
2004-01-30 23:07:56 +08:00
|
|
|
def readable?(fileName)
|
|
|
|
unix_mode_cmp(fileName, 0444)
|
|
|
|
end
|
2015-03-21 18:14:21 +08:00
|
|
|
alias readable_real? readable?
|
2004-01-30 23:07:56 +08:00
|
|
|
|
|
|
|
def writable?(fileName)
|
|
|
|
unix_mode_cmp(fileName, 0222)
|
|
|
|
end
|
2015-03-21 18:14:21 +08:00
|
|
|
alias writable_real? writable?
|
2004-01-30 23:07:56 +08:00
|
|
|
|
|
|
|
def executable?(fileName)
|
|
|
|
unix_mode_cmp(fileName, 0111)
|
|
|
|
end
|
2015-03-21 18:14:21 +08:00
|
|
|
alias executable_real? executable?
|
2004-01-30 23:07:56 +08:00
|
|
|
|
2003-08-13 17:44:47 +08:00
|
|
|
def setuid?(fileName)
|
2004-01-30 23:07:56 +08:00
|
|
|
unix_mode_cmp(fileName, 04000)
|
2003-08-13 17:44:47 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def setgid?(fileName)
|
2004-01-30 23:07:56 +08:00
|
|
|
unix_mode_cmp(fileName, 02000)
|
2003-08-13 17:44:47 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2003-08-13 17:44:47 +08:00
|
|
|
def sticky?(fileName)
|
2004-01-30 23:07:56 +08:00
|
|
|
unix_mode_cmp(fileName, 01000)
|
2003-08-13 17:44:47 +08:00
|
|
|
end
|
2003-08-13 15:51:42 +08:00
|
|
|
|
2003-08-13 21:18:25 +08:00
|
|
|
def umask(*args)
|
2003-08-18 00:28:18 +08:00
|
|
|
::File.umask(*args)
|
2003-08-13 21:18:25 +08:00
|
|
|
end
|
|
|
|
|
2015-03-21 04:09:41 +08:00
|
|
|
def truncate(_fileName, _len)
|
2015-03-21 16:27:44 +08:00
|
|
|
raise StandardError, 'truncate not supported'
|
2003-08-13 21:18:25 +08:00
|
|
|
end
|
|
|
|
|
2002-07-27 06:20:25 +08:00
|
|
|
def directory?(fileName)
|
2011-11-16 23:09:14 +08:00
|
|
|
entry = @mappedZip.find_entry(fileName)
|
2015-06-08 15:29:08 +08:00
|
|
|
expand_path(fileName) == '/' || (!entry.nil? && entry.directory?)
|
2002-07-27 06:20:25 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2015-03-21 16:27:44 +08:00
|
|
|
def open(fileName, openMode = 'r', permissionInt = 0644, &block)
|
|
|
|
openMode.gsub!('b', '') # ignore b option
|
2003-08-19 00:39:50 +08:00
|
|
|
case openMode
|
2015-03-21 16:27:44 +08:00
|
|
|
when 'r'
|
2015-03-21 16:12:01 +08:00
|
|
|
@mappedZip.get_input_stream(fileName, &block)
|
2015-03-21 16:27:44 +08:00
|
|
|
when 'w'
|
2015-03-21 16:12:01 +08:00
|
|
|
@mappedZip.get_output_stream(fileName, permissionInt, &block)
|
|
|
|
else
|
2015-03-21 16:27:44 +08:00
|
|
|
raise StandardError, "openmode '#{openMode} not supported" unless openMode == 'r'
|
2003-08-19 00:39:50 +08:00
|
|
|
end
|
2002-07-27 06:20:25 +08:00
|
|
|
end
|
2002-07-27 21:25:16 +08:00
|
|
|
|
2015-03-21 16:27:44 +08:00
|
|
|
def new(fileName, openMode = 'r')
|
2011-11-16 23:09:14 +08:00
|
|
|
open(fileName, openMode)
|
2002-07-27 21:25:16 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2002-07-27 06:20:25 +08:00
|
|
|
def size(fileName)
|
2011-11-16 23:09:14 +08:00
|
|
|
@mappedZip.get_entry(fileName).size
|
2002-07-27 06:20:25 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2005-02-18 04:27:02 +08:00
|
|
|
# Returns nil for not found and nil for directories
|
2002-07-27 06:20:25 +08:00
|
|
|
def size?(fileName)
|
2011-11-16 23:09:14 +08:00
|
|
|
entry = @mappedZip.find_entry(fileName)
|
2015-06-08 15:30:12 +08:00
|
|
|
(entry.nil? || entry.directory?) ? nil : entry.size
|
2002-07-27 06:20:25 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2004-01-30 23:07:56 +08:00
|
|
|
def chown(ownerInt, groupInt, *filenames)
|
2015-03-21 16:10:37 +08:00
|
|
|
filenames.each do |fileName|
|
2004-01-30 23:07:56 +08:00
|
|
|
e = get_entry(fileName)
|
2015-03-25 00:09:22 +08:00
|
|
|
e.extra.create('IUnix') unless e.extra.member?('IUnix')
|
2015-03-21 16:27:44 +08:00
|
|
|
e.extra['IUnix'].uid = ownerInt
|
|
|
|
e.extra['IUnix'].gid = groupInt
|
2015-03-21 16:10:37 +08:00
|
|
|
end
|
2003-08-13 21:18:25 +08:00
|
|
|
filenames.size
|
|
|
|
end
|
|
|
|
|
2015-03-23 00:43:44 +08:00
|
|
|
def chmod(modeInt, *filenames)
|
2015-03-21 16:10:37 +08:00
|
|
|
filenames.each do |fileName|
|
2004-01-30 23:07:56 +08:00
|
|
|
e = get_entry(fileName)
|
|
|
|
e.fstype = 3 # force convertion filesystem type to unix
|
2011-11-17 17:48:42 +08:00
|
|
|
e.unix_perms = modeInt
|
2013-06-03 02:33:03 +08:00
|
|
|
e.external_file_attributes = modeInt << 16
|
2011-11-17 17:48:42 +08:00
|
|
|
e.dirty = true
|
2015-03-21 16:10:37 +08:00
|
|
|
end
|
2003-08-13 21:18:25 +08:00
|
|
|
filenames.size
|
|
|
|
end
|
|
|
|
|
2002-07-27 06:20:25 +08:00
|
|
|
def zero?(fileName)
|
2011-11-16 23:04:28 +08:00
|
|
|
sz = size(fileName)
|
2015-06-08 15:30:12 +08:00
|
|
|
sz.nil? || sz == 0
|
2002-07-27 06:20:25 +08:00
|
|
|
rescue Errno::ENOENT
|
2011-11-16 23:04:28 +08:00
|
|
|
false
|
2002-07-27 06:20:25 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2002-07-27 06:20:25 +08:00
|
|
|
def file?(fileName)
|
2011-11-16 23:04:28 +08:00
|
|
|
entry = @mappedZip.find_entry(fileName)
|
2015-06-08 15:29:08 +08:00
|
|
|
!entry.nil? && entry.file?
|
2015-03-21 03:43:29 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2002-07-27 06:20:25 +08:00
|
|
|
def dirname(fileName)
|
2011-11-16 23:04:28 +08:00
|
|
|
::File.dirname(fileName)
|
2002-07-27 06:20:25 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2002-07-27 06:20:25 +08:00
|
|
|
def basename(fileName)
|
2011-11-16 23:04:28 +08:00
|
|
|
::File.basename(fileName)
|
2002-07-27 06:20:25 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2002-07-27 06:20:25 +08:00
|
|
|
def split(fileName)
|
2011-11-16 23:04:28 +08:00
|
|
|
::File.split(fileName)
|
2002-07-27 06:20:25 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2002-07-27 06:20:25 +08:00
|
|
|
def join(*fragments)
|
2011-11-16 23:04:28 +08:00
|
|
|
::File.join(*fragments)
|
2002-07-27 06:20:25 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2004-01-30 23:07:56 +08:00
|
|
|
def utime(modifiedTime, *fileNames)
|
2015-03-21 16:10:37 +08:00
|
|
|
fileNames.each do |fileName|
|
2004-01-30 23:07:56 +08:00
|
|
|
get_entry(fileName).time = modifiedTime
|
2015-03-21 16:10:37 +08:00
|
|
|
end
|
2003-08-14 11:40:49 +08:00
|
|
|
end
|
|
|
|
|
2002-07-27 06:20:25 +08:00
|
|
|
def mtime(fileName)
|
2011-11-16 23:04:28 +08:00
|
|
|
@mappedZip.get_entry(fileName).mtime
|
2002-07-27 06:20:25 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2003-08-14 11:40:49 +08:00
|
|
|
def atime(fileName)
|
2004-01-30 23:07:56 +08:00
|
|
|
e = get_entry(fileName)
|
2015-03-21 16:27:44 +08:00
|
|
|
if e.extra.member? 'UniversalTime'
|
|
|
|
e.extra['UniversalTime'].atime
|
|
|
|
elsif e.extra.member? 'NTFS'
|
|
|
|
e.extra['NTFS'].atime
|
2004-01-30 23:07:56 +08:00
|
|
|
end
|
2003-08-14 11:40:49 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2003-08-14 11:40:49 +08:00
|
|
|
def ctime(fileName)
|
2004-01-30 23:07:56 +08:00
|
|
|
e = get_entry(fileName)
|
2015-03-21 16:27:44 +08:00
|
|
|
if e.extra.member? 'UniversalTime'
|
|
|
|
e.extra['UniversalTime'].ctime
|
|
|
|
elsif e.extra.member? 'NTFS'
|
|
|
|
e.extra['NTFS'].ctime
|
2004-01-30 23:07:56 +08:00
|
|
|
end
|
2003-08-14 11:40:49 +08:00
|
|
|
end
|
|
|
|
|
2015-03-21 04:09:41 +08:00
|
|
|
def pipe?(_filename)
|
2011-11-16 23:04:28 +08:00
|
|
|
false
|
2002-07-27 06:20:25 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2015-03-21 04:09:41 +08:00
|
|
|
def blockdev?(_filename)
|
2011-11-16 23:04:28 +08:00
|
|
|
false
|
2002-07-27 06:20:25 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2015-03-21 04:09:41 +08:00
|
|
|
def chardev?(_filename)
|
2011-11-16 23:04:28 +08:00
|
|
|
false
|
2002-09-12 04:18:24 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2015-03-21 04:09:41 +08:00
|
|
|
def symlink?(_fileName)
|
2011-11-16 23:04:28 +08:00
|
|
|
false
|
2002-07-27 06:20:25 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2015-03-21 04:09:41 +08:00
|
|
|
def socket?(_fileName)
|
2011-11-16 23:04:28 +08:00
|
|
|
false
|
2002-07-27 06:20:25 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2002-07-27 06:20:25 +08:00
|
|
|
def ftype(fileName)
|
2015-03-21 16:27:44 +08:00
|
|
|
@mappedZip.get_entry(fileName).directory? ? 'directory' : 'file'
|
2002-07-27 06:20:25 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2015-03-21 04:09:41 +08:00
|
|
|
def readlink(_fileName)
|
2015-03-21 16:27:44 +08:00
|
|
|
raise NotImplementedError, 'The readlink() function is not implemented'
|
2002-07-27 06:20:25 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2015-03-21 04:09:41 +08:00
|
|
|
def symlink(_fileName, _symlinkName)
|
2015-03-21 16:27:44 +08:00
|
|
|
raise NotImplementedError, 'The symlink() function is not implemented'
|
2002-07-27 06:23:32 +08:00
|
|
|
end
|
2002-07-27 06:25:36 +08:00
|
|
|
|
2015-03-21 04:09:41 +08:00
|
|
|
def link(_fileName, _symlinkName)
|
2015-03-21 16:27:44 +08:00
|
|
|
raise NotImplementedError, 'The link() function is not implemented'
|
2002-07-27 06:25:36 +08:00
|
|
|
end
|
2002-07-27 06:30:04 +08:00
|
|
|
|
|
|
|
def pipe
|
2015-03-21 16:27:44 +08:00
|
|
|
raise NotImplementedError, 'The pipe() function is not implemented'
|
2002-07-27 06:30:04 +08:00
|
|
|
end
|
2002-09-12 04:18:24 +08:00
|
|
|
|
2003-08-13 16:39:01 +08:00
|
|
|
def stat(fileName)
|
2015-03-25 00:09:22 +08:00
|
|
|
raise Errno::ENOENT, fileName unless exists?(fileName)
|
2003-08-13 16:39:01 +08:00
|
|
|
ZipFsStat.new(self, fileName)
|
|
|
|
end
|
|
|
|
|
2015-03-21 18:14:21 +08:00
|
|
|
alias lstat stat
|
2003-08-13 21:18:25 +08:00
|
|
|
|
2002-09-12 04:18:24 +08:00
|
|
|
def readlines(fileName)
|
2011-11-16 23:04:28 +08:00
|
|
|
open(fileName) { |is| is.readlines }
|
2002-09-12 04:18:24 +08:00
|
|
|
end
|
|
|
|
|
2003-08-18 00:28:18 +08:00
|
|
|
def read(fileName)
|
2003-08-20 23:30:03 +08:00
|
|
|
@mappedZip.read(fileName)
|
2003-08-18 00:28:18 +08:00
|
|
|
end
|
|
|
|
|
2002-09-12 04:18:24 +08:00
|
|
|
def popen(*args, &aProc)
|
2013-06-03 15:56:24 +08:00
|
|
|
::File.popen(*args, &aProc)
|
2002-09-12 04:18:24 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def foreach(fileName, aSep = $/, &aProc)
|
2011-11-16 23:04:28 +08:00
|
|
|
open(fileName) { |is| is.each_line(aSep, &aProc) }
|
2002-09-12 04:18:24 +08:00
|
|
|
end
|
2002-09-12 06:10:34 +08:00
|
|
|
|
|
|
|
def delete(*args)
|
2015-03-21 16:10:37 +08:00
|
|
|
args.each do |fileName|
|
2011-11-16 23:04:28 +08:00
|
|
|
if directory?(fileName)
|
|
|
|
raise Errno::EISDIR, "Is a directory - \"#{fileName}\""
|
|
|
|
end
|
|
|
|
@mappedZip.remove(fileName)
|
2015-03-21 16:10:37 +08:00
|
|
|
end
|
2002-09-12 06:10:34 +08:00
|
|
|
end
|
|
|
|
|
2003-08-13 21:18:25 +08:00
|
|
|
def rename(fileToRename, newName)
|
2003-08-20 23:30:03 +08:00
|
|
|
@mappedZip.rename(fileToRename, newName) { true }
|
2003-08-13 21:18:25 +08:00
|
|
|
end
|
|
|
|
|
2015-03-21 18:14:21 +08:00
|
|
|
alias unlink delete
|
2002-09-12 06:10:34 +08:00
|
|
|
|
2003-08-20 21:39:56 +08:00
|
|
|
def expand_path(aPath)
|
2003-08-20 23:30:03 +08:00
|
|
|
@mappedZip.expand_path(aPath)
|
2003-08-20 21:39:56 +08:00
|
|
|
end
|
2002-07-27 05:32:12 +08:00
|
|
|
end
|
2003-08-20 21:39:56 +08:00
|
|
|
|
2005-02-18 04:27:02 +08:00
|
|
|
# Instances of this class are normally accessed via the accessor
|
|
|
|
# ZipFile::dir. An instance of ZipFsDir behaves like ruby's
|
|
|
|
# builtin Dir (class) object, except it works on ZipFile entries.
|
|
|
|
#
|
|
|
|
# The individual methods are not documented due to their
|
|
|
|
# similarity with the methods in Dir
|
2003-08-20 22:10:20 +08:00
|
|
|
class ZipFsDir
|
2003-08-20 23:30:03 +08:00
|
|
|
def initialize(mappedZip)
|
|
|
|
@mappedZip = mappedZip
|
2003-08-20 21:39:56 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2003-08-20 22:10:20 +08:00
|
|
|
attr_writer :file
|
2003-08-21 20:32:01 +08:00
|
|
|
|
|
|
|
def new(aDirectoryName)
|
|
|
|
ZipFsDirIterator.new(entries(aDirectoryName))
|
|
|
|
end
|
|
|
|
|
|
|
|
def open(aDirectoryName)
|
|
|
|
dirIt = new(aDirectoryName)
|
|
|
|
if block_given?
|
|
|
|
begin
|
|
|
|
yield(dirIt)
|
|
|
|
return nil
|
|
|
|
ensure
|
|
|
|
dirIt.close
|
|
|
|
end
|
|
|
|
end
|
|
|
|
dirIt
|
|
|
|
end
|
|
|
|
|
2015-03-23 00:37:59 +08:00
|
|
|
def pwd
|
|
|
|
@mappedZip.pwd
|
|
|
|
end
|
2015-03-21 18:14:21 +08:00
|
|
|
alias getwd pwd
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2003-08-20 22:10:20 +08:00
|
|
|
def chdir(aDirectoryName)
|
|
|
|
unless @file.stat(aDirectoryName).directory?
|
|
|
|
raise Errno::EINVAL, "Invalid argument - #{aDirectoryName}"
|
|
|
|
end
|
2003-08-20 23:30:03 +08:00
|
|
|
@mappedZip.pwd = @file.expand_path(aDirectoryName)
|
2003-08-20 21:39:56 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2003-08-20 22:10:20 +08:00
|
|
|
def entries(aDirectoryName)
|
2003-08-21 04:44:12 +08:00
|
|
|
entries = []
|
|
|
|
foreach(aDirectoryName) { |e| entries << e }
|
|
|
|
entries
|
|
|
|
end
|
|
|
|
|
2015-03-23 00:41:47 +08:00
|
|
|
def glob(*args, &block)
|
|
|
|
@mappedZip.glob(*args, &block)
|
2012-05-19 05:57:19 +08:00
|
|
|
end
|
|
|
|
|
2003-08-21 04:44:12 +08:00
|
|
|
def foreach(aDirectoryName)
|
2003-08-20 22:10:20 +08:00
|
|
|
unless @file.stat(aDirectoryName).directory?
|
|
|
|
raise Errno::ENOTDIR, aDirectoryName
|
|
|
|
end
|
2012-02-01 17:59:56 +08:00
|
|
|
path = @file.expand_path(aDirectoryName)
|
|
|
|
path << '/' unless path.end_with?('/')
|
2011-11-16 23:04:28 +08:00
|
|
|
path = Regexp.escape(path)
|
2003-08-20 23:30:03 +08:00
|
|
|
subDirEntriesRegex = Regexp.new("^#{path}([^/]+)$")
|
2015-03-21 16:10:37 +08:00
|
|
|
@mappedZip.each do |fileName|
|
2003-08-20 23:30:03 +08:00
|
|
|
match = subDirEntriesRegex.match(fileName)
|
2015-06-08 15:30:12 +08:00
|
|
|
yield(match[1]) unless match.nil?
|
2015-03-21 16:10:37 +08:00
|
|
|
end
|
2003-08-20 22:10:20 +08:00
|
|
|
end
|
2003-08-21 04:44:12 +08:00
|
|
|
|
2003-08-20 22:10:20 +08:00
|
|
|
def delete(entryName)
|
|
|
|
unless @file.stat(entryName).directory?
|
|
|
|
raise Errno::EINVAL, "Invalid argument - #{entryName}"
|
|
|
|
end
|
2003-08-20 23:30:03 +08:00
|
|
|
@mappedZip.remove(entryName)
|
2003-08-20 22:10:20 +08:00
|
|
|
end
|
2015-03-21 18:14:21 +08:00
|
|
|
alias rmdir delete
|
|
|
|
alias unlink delete
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2006-02-23 06:44:28 +08:00
|
|
|
def mkdir(entryName, permissionInt = 0755)
|
2003-08-20 23:30:03 +08:00
|
|
|
@mappedZip.mkdir(entryName, permissionInt)
|
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2015-03-21 04:09:41 +08:00
|
|
|
def chroot(*_args)
|
2015-03-21 16:27:44 +08:00
|
|
|
raise NotImplementedError, 'The chroot() function is not implemented'
|
2003-08-21 00:08:07 +08:00
|
|
|
end
|
2003-08-20 23:30:03 +08:00
|
|
|
end
|
|
|
|
|
2005-02-18 04:27:02 +08:00
|
|
|
class ZipFsDirIterator # :nodoc:all
|
2003-08-21 20:19:00 +08:00
|
|
|
include Enumerable
|
|
|
|
|
|
|
|
def initialize(arrayOfFileNames)
|
|
|
|
@fileNames = arrayOfFileNames
|
|
|
|
@index = 0
|
|
|
|
end
|
|
|
|
|
|
|
|
def close
|
|
|
|
@fileNames = nil
|
|
|
|
end
|
|
|
|
|
|
|
|
def each(&aProc)
|
2015-06-08 15:30:12 +08:00
|
|
|
raise IOError, 'closed directory' if @fileNames.nil?
|
2003-08-21 20:19:00 +08:00
|
|
|
@fileNames.each(&aProc)
|
|
|
|
end
|
|
|
|
|
|
|
|
def read
|
2015-06-08 15:30:12 +08:00
|
|
|
raise IOError, 'closed directory' if @fileNames.nil?
|
2015-03-23 01:03:50 +08:00
|
|
|
@fileNames[(@index += 1) - 1]
|
2003-08-21 20:19:00 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def rewind
|
2015-06-08 15:30:12 +08:00
|
|
|
raise IOError, 'closed directory' if @fileNames.nil?
|
2003-08-21 20:19:00 +08:00
|
|
|
@index = 0
|
|
|
|
end
|
|
|
|
|
|
|
|
def seek(anIntegerPosition)
|
2015-06-08 15:30:12 +08:00
|
|
|
raise IOError, 'closed directory' if @fileNames.nil?
|
2003-08-21 20:19:00 +08:00
|
|
|
@index = anIntegerPosition
|
|
|
|
end
|
|
|
|
|
|
|
|
def tell
|
2015-06-08 15:30:12 +08:00
|
|
|
raise IOError, 'closed directory' if @fileNames.nil?
|
2003-08-21 20:19:00 +08:00
|
|
|
@index
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-09-25 17:40:35 +08:00
|
|
|
# All access to Zip::File from ZipFsFile and ZipFsDir goes through a
|
2003-08-20 23:30:03 +08:00
|
|
|
# ZipFileNameMapper, which has one responsibility: ensure
|
2005-02-18 04:27:02 +08:00
|
|
|
class ZipFileNameMapper # :nodoc:all
|
2003-08-20 23:30:03 +08:00
|
|
|
include Enumerable
|
|
|
|
|
|
|
|
def initialize(zipFile)
|
|
|
|
@zipFile = zipFile
|
2015-03-21 16:27:44 +08:00
|
|
|
@pwd = '/'
|
2003-08-20 22:10:20 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2003-08-20 23:30:03 +08:00
|
|
|
attr_accessor :pwd
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2003-08-20 23:30:03 +08:00
|
|
|
def find_entry(fileName)
|
|
|
|
@zipFile.find_entry(expand_to_entry(fileName))
|
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2003-08-20 23:30:03 +08:00
|
|
|
def get_entry(fileName)
|
|
|
|
@zipFile.get_entry(expand_to_entry(fileName))
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_input_stream(fileName, &aProc)
|
|
|
|
@zipFile.get_input_stream(expand_to_entry(fileName), &aProc)
|
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2011-11-17 17:48:42 +08:00
|
|
|
def get_output_stream(fileName, permissionInt = nil, &aProc)
|
|
|
|
@zipFile.get_output_stream(expand_to_entry(fileName), permissionInt, &aProc)
|
2003-08-20 23:30:03 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def read(fileName)
|
|
|
|
@zipFile.read(expand_to_entry(fileName))
|
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2003-08-20 23:30:03 +08:00
|
|
|
def remove(fileName)
|
|
|
|
@zipFile.remove(expand_to_entry(fileName))
|
|
|
|
end
|
|
|
|
|
|
|
|
def rename(fileName, newName, &continueOnExistsProc)
|
2015-03-21 03:43:29 +08:00
|
|
|
@zipFile.rename(expand_to_entry(fileName), expand_to_entry(newName),
|
2003-08-20 23:30:03 +08:00
|
|
|
&continueOnExistsProc)
|
|
|
|
end
|
|
|
|
|
2006-02-23 06:44:28 +08:00
|
|
|
def mkdir(fileName, permissionInt = 0755)
|
2003-08-20 23:30:03 +08:00
|
|
|
@zipFile.mkdir(expand_to_entry(fileName), permissionInt)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Turns entries into strings and adds leading /
|
|
|
|
# and removes trailing slash on directories
|
|
|
|
def each
|
2015-03-21 16:10:37 +08:00
|
|
|
@zipFile.each do |e|
|
2015-03-23 01:03:50 +08:00
|
|
|
yield('/' + e.to_s.chomp('/'))
|
2015-03-21 16:10:37 +08:00
|
|
|
end
|
2003-08-20 23:30:03 +08:00
|
|
|
end
|
2011-11-16 23:09:14 +08:00
|
|
|
|
2003-08-20 22:10:20 +08:00
|
|
|
def expand_path(aPath)
|
2015-03-21 16:27:44 +08:00
|
|
|
expanded = aPath.start_with?('/') ? aPath : ::File.join(@pwd, aPath)
|
|
|
|
expanded.gsub!(/\/\.(\/|$)/, '')
|
|
|
|
expanded.gsub!(/[^\/]+\/\.\.(\/|$)/, '')
|
|
|
|
expanded.empty? ? '/' : expanded
|
2003-08-20 22:10:20 +08:00
|
|
|
end
|
2003-08-20 23:30:03 +08:00
|
|
|
|
|
|
|
private
|
|
|
|
|
2003-08-20 22:10:20 +08:00
|
|
|
def expand_to_entry(aPath)
|
2012-02-01 18:02:56 +08:00
|
|
|
expand_path(aPath)[1..-1]
|
2003-08-19 21:07:24 +08:00
|
|
|
end
|
2003-08-20 21:39:56 +08:00
|
|
|
end
|
2003-08-19 21:07:24 +08:00
|
|
|
end
|
|
|
|
|
2013-06-03 15:56:24 +08:00
|
|
|
class File
|
|
|
|
include FileSystem
|
2003-08-13 16:00:52 +08:00
|
|
|
end
|
2002-07-26 22:12:34 +08:00
|
|
|
end
|
2003-08-13 16:00:52 +08:00
|
|
|
|
2003-08-13 16:02:32 +08:00
|
|
|
# Copyright (C) 2002, 2003 Thomas Sondergaard
|
|
|
|
# rubyzip is free software; you can redistribute it and/or
|
|
|
|
# modify it under the terms of the ruby license.
|