rubyzip 0.9.9 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +284 -41
- data/Rakefile +11 -6
- data/TODO +0 -1
- data/lib/zip/central_directory.rb +208 -0
- data/lib/zip/compressor.rb +1 -2
- data/lib/zip/constants.rb +59 -7
- data/lib/zip/crypto/encryption.rb +11 -0
- data/lib/zip/crypto/null_encryption.rb +43 -0
- data/lib/zip/crypto/traditional_encryption.rb +99 -0
- data/lib/zip/decompressor.rb +4 -4
- data/lib/zip/deflater.rb +17 -13
- data/lib/zip/dos_time.rb +13 -14
- data/lib/zip/entry.rb +700 -0
- data/lib/zip/entry_set.rb +86 -0
- data/lib/zip/errors.rb +18 -0
- data/lib/zip/extra_field/generic.rb +43 -0
- data/lib/zip/extra_field/ntfs.rb +90 -0
- data/lib/zip/extra_field/old_unix.rb +44 -0
- data/lib/zip/extra_field/universal_time.rb +47 -0
- data/lib/zip/extra_field/unix.rb +37 -0
- data/lib/zip/extra_field/zip64.rb +68 -0
- data/lib/zip/extra_field/zip64_placeholder.rb +15 -0
- data/lib/zip/extra_field.rb +101 -0
- data/lib/zip/file.rb +443 -0
- data/lib/zip/{zipfilesystem.rb → filesystem.rb} +162 -157
- data/lib/zip/inflater.rb +29 -28
- data/lib/zip/input_stream.rb +173 -0
- data/lib/zip/ioextras/abstract_input_stream.rb +111 -0
- data/lib/zip/ioextras/abstract_output_stream.rb +43 -0
- data/lib/zip/ioextras.rb +21 -149
- data/lib/zip/null_compressor.rb +2 -2
- data/lib/zip/null_decompressor.rb +8 -6
- data/lib/zip/null_input_stream.rb +3 -2
- data/lib/zip/output_stream.rb +189 -0
- data/lib/zip/pass_thru_compressor.rb +6 -6
- data/lib/zip/pass_thru_decompressor.rb +19 -19
- data/lib/zip/{zip_streamable_directory.rb → streamable_directory.rb} +3 -3
- data/lib/zip/streamable_stream.rb +56 -0
- data/lib/zip/version.rb +3 -0
- data/lib/zip.rb +71 -0
- data/samples/example.rb +44 -32
- data/samples/example_filesystem.rb +16 -18
- data/samples/example_recursive.rb +33 -28
- data/samples/{gtkRubyzip.rb → gtk_ruby_zip.rb} +26 -28
- data/samples/qtzip.rb +22 -31
- data/samples/write_simple.rb +12 -13
- data/samples/zipfind.rb +31 -39
- data/test/basic_zip_file_test.rb +60 -0
- data/test/case_sensitivity_test.rb +69 -0
- data/test/central_directory_entry_test.rb +69 -0
- data/test/central_directory_test.rb +100 -0
- data/test/crypto/null_encryption_test.rb +57 -0
- data/test/crypto/traditional_encryption_test.rb +80 -0
- data/test/data/WarnInvalidDate.zip +0 -0
- data/test/data/file1.txt +46 -0
- data/test/data/file1.txt.deflatedData +0 -0
- data/test/data/file2.txt +1504 -0
- data/test/data/globTest/foo/bar/baz/foo.txt +0 -0
- data/test/data/globTest/foo.txt +0 -0
- data/test/data/globTest/food.txt +0 -0
- data/test/data/globTest.zip +0 -0
- data/test/data/gpbit3stored.zip +0 -0
- data/test/data/mimetype +1 -0
- data/test/data/notzippedruby.rb +7 -0
- data/test/data/ntfs.zip +0 -0
- data/test/data/oddExtraField.zip +0 -0
- data/test/data/path_traversal/Makefile +10 -0
- data/test/data/path_traversal/jwilk/README.md +5 -0
- data/test/data/path_traversal/jwilk/absolute1.zip +0 -0
- data/test/data/path_traversal/jwilk/absolute2.zip +0 -0
- data/test/data/path_traversal/jwilk/dirsymlink.zip +0 -0
- data/test/data/path_traversal/jwilk/dirsymlink2a.zip +0 -0
- data/test/data/path_traversal/jwilk/dirsymlink2b.zip +0 -0
- data/test/data/path_traversal/jwilk/relative0.zip +0 -0
- data/test/data/path_traversal/jwilk/relative2.zip +0 -0
- data/test/data/path_traversal/jwilk/symlink.zip +0 -0
- data/test/data/path_traversal/relative1.zip +0 -0
- data/test/data/path_traversal/tilde.zip +0 -0
- data/test/data/path_traversal/tuzovakaoff/README.md +3 -0
- data/test/data/path_traversal/tuzovakaoff/absolutepath.zip +0 -0
- data/test/data/path_traversal/tuzovakaoff/symlink.zip +0 -0
- data/test/data/rubycode.zip +0 -0
- data/test/data/rubycode2.zip +0 -0
- data/test/data/test.xls +0 -0
- data/test/data/testDirectory.bin +0 -0
- data/test/data/zip64-sample.zip +0 -0
- data/test/data/zipWithDirs.zip +0 -0
- data/test/data/zipWithEncryption.zip +0 -0
- data/test/deflater_test.rb +65 -0
- data/test/encryption_test.rb +42 -0
- data/test/entry_set_test.rb +163 -0
- data/test/entry_test.rb +154 -0
- data/test/errors_test.rb +35 -0
- data/test/extra_field_test.rb +76 -0
- data/test/file_extract_directory_test.rb +54 -0
- data/test/file_extract_test.rb +145 -0
- data/test/file_permissions_test.rb +65 -0
- data/test/file_split_test.rb +57 -0
- data/test/file_test.rb +666 -0
- data/test/filesystem/dir_iterator_test.rb +58 -0
- data/test/filesystem/directory_test.rb +139 -0
- data/test/filesystem/file_mutating_test.rb +87 -0
- data/test/filesystem/file_nonmutating_test.rb +508 -0
- data/test/filesystem/file_stat_test.rb +64 -0
- data/test/gentestfiles.rb +126 -0
- data/test/inflater_test.rb +14 -0
- data/test/input_stream_test.rb +182 -0
- data/test/ioextras/abstract_input_stream_test.rb +102 -0
- data/test/ioextras/abstract_output_stream_test.rb +106 -0
- data/test/ioextras/fake_io_test.rb +18 -0
- data/test/local_entry_test.rb +154 -0
- data/test/output_stream_test.rb +128 -0
- data/test/pass_thru_compressor_test.rb +30 -0
- data/test/pass_thru_decompressor_test.rb +14 -0
- data/test/path_traversal_test.rb +141 -0
- data/test/samples/example_recursive_test.rb +37 -0
- data/test/settings_test.rb +95 -0
- data/test/test_helper.rb +234 -0
- data/test/unicode_file_names_and_comments_test.rb +62 -0
- data/test/zip64_full_test.rb +51 -0
- data/test/zip64_support_test.rb +14 -0
- metadata +274 -41
- data/NEWS +0 -172
- data/lib/zip/settings.rb +0 -10
- data/lib/zip/tempfile_bugfixed.rb +0 -195
- data/lib/zip/zip.rb +0 -56
- data/lib/zip/zip_central_directory.rb +0 -135
- data/lib/zip/zip_entry.rb +0 -638
- data/lib/zip/zip_entry_set.rb +0 -77
- data/lib/zip/zip_extra_field.rb +0 -213
- data/lib/zip/zip_file.rb +0 -340
- data/lib/zip/zip_input_stream.rb +0 -144
- data/lib/zip/zip_output_stream.rb +0 -173
- data/lib/zip/zip_streamable_stream.rb +0 -47
@@ -1,41 +1,39 @@
|
|
1
|
-
require 'zip
|
1
|
+
require 'zip'
|
2
2
|
|
3
3
|
module Zip
|
4
|
-
|
5
|
-
#
|
6
|
-
# a zip archive that is similar to ruby's builtin File and Dir
|
4
|
+
# The ZipFileSystem API provides an API for accessing entries in
|
5
|
+
# a zip archive that is similar to ruby's builtin File and Dir
|
7
6
|
# classes.
|
8
7
|
#
|
9
|
-
# Requiring 'zip/
|
10
|
-
# making the methods in this module available on
|
8
|
+
# Requiring 'zip/filesystem' includes this module in Zip::File
|
9
|
+
# making the methods in this module available on Zip::File objects.
|
11
10
|
#
|
12
|
-
# Using this API the following example creates a new zip file
|
11
|
+
# Using this API the following example creates a new zip file
|
13
12
|
# <code>my.zip</code> containing a normal entry with the name
|
14
13
|
# <code>first.txt</code>, a directory entry named <code>mydir</code>
|
15
14
|
# and finally another normal entry named <code>second.txt</code>
|
16
15
|
#
|
17
|
-
# require 'zip/
|
18
|
-
#
|
19
|
-
# Zip::
|
16
|
+
# require 'zip/filesystem'
|
17
|
+
#
|
18
|
+
# Zip::File.open("my.zip", Zip::File::CREATE) {
|
20
19
|
# |zipfile|
|
21
20
|
# zipfile.file.open("first.txt", "w") { |f| f.puts "Hello world" }
|
22
21
|
# zipfile.dir.mkdir("mydir")
|
23
22
|
# zipfile.file.open("mydir/second.txt", "w") { |f| f.puts "Hello again" }
|
24
23
|
# }
|
25
24
|
#
|
26
|
-
# Reading is as easy as writing, as the following example shows. The
|
25
|
+
# Reading is as easy as writing, as the following example shows. The
|
27
26
|
# example writes the contents of <code>first.txt</code> from zip archive
|
28
27
|
# <code>my.zip</code> to standard out.
|
29
28
|
#
|
30
|
-
# require 'zip/
|
31
|
-
#
|
32
|
-
# Zip::
|
29
|
+
# require 'zip/filesystem'
|
30
|
+
#
|
31
|
+
# Zip::File.open("my.zip") {
|
33
32
|
# |zipfile|
|
34
33
|
# puts zipfile.file.read("first.txt")
|
35
34
|
# }
|
36
35
|
|
37
|
-
module
|
38
|
-
|
36
|
+
module FileSystem
|
39
37
|
def initialize # :nodoc:
|
40
38
|
mappedZip = ZipFileNameMapper.new(self)
|
41
39
|
@zipFsDir = ZipFsDir.new(mappedZip)
|
@@ -45,44 +43,40 @@ module Zip
|
|
45
43
|
end
|
46
44
|
|
47
45
|
# Returns a ZipFsDir which is much like ruby's builtin Dir (class)
|
48
|
-
# object, except it works on the
|
46
|
+
# object, except it works on the Zip::File on which this method is
|
49
47
|
# invoked
|
50
48
|
def dir
|
51
49
|
@zipFsDir
|
52
50
|
end
|
53
51
|
|
54
52
|
# Returns a ZipFsFile which is much like ruby's builtin File (class)
|
55
|
-
# object, except it works on the
|
53
|
+
# object, except it works on the Zip::File on which this method is
|
56
54
|
# invoked
|
57
55
|
def file
|
58
56
|
@zipFsFile
|
59
57
|
end
|
60
58
|
|
61
59
|
# Instances of this class are normally accessed via the accessor
|
62
|
-
#
|
63
|
-
# builtin File (class) object, except it works on
|
60
|
+
# Zip::File::file. An instance of ZipFsFile behaves like ruby's
|
61
|
+
# builtin File (class) object, except it works on Zip::File entries.
|
64
62
|
#
|
65
63
|
# The individual methods are not documented due to their
|
66
64
|
# similarity with the methods in File
|
67
65
|
class ZipFsFile
|
68
|
-
|
69
66
|
attr_writer :dir
|
70
|
-
#
|
67
|
+
# protected :dir
|
71
68
|
|
72
69
|
class ZipFsStat
|
73
|
-
|
74
70
|
class << self
|
75
|
-
|
76
71
|
def delegate_to_fs_file(*methods)
|
77
72
|
methods.each do |method|
|
78
|
-
|
73
|
+
class_eval <<-end_eval, __FILE__, __LINE__ + 1
|
79
74
|
def #{method} # def file?
|
80
75
|
@zipFsFile.#{method}(@entryName) # @zipFsFile.file?(@entryName)
|
81
76
|
end # end
|
82
77
|
end_eval
|
83
78
|
end
|
84
79
|
end
|
85
|
-
|
86
80
|
end
|
87
81
|
|
88
82
|
def initialize(zipFsFile, entryName)
|
@@ -91,15 +85,17 @@ module Zip
|
|
91
85
|
end
|
92
86
|
|
93
87
|
def kind_of?(t)
|
94
|
-
super || t == ::File::Stat
|
88
|
+
super || t == ::File::Stat
|
95
89
|
end
|
96
90
|
|
97
91
|
delegate_to_fs_file :file?, :directory?, :pipe?, :chardev?, :symlink?,
|
98
|
-
|
99
|
-
|
100
|
-
|
92
|
+
:socket?, :blockdev?, :readable?, :readable_real?, :writable?, :ctime,
|
93
|
+
:writable_real?, :executable?, :executable_real?, :sticky?, :owned?,
|
94
|
+
:grpowned?, :setuid?, :setgid?, :zero?, :size, :size?, :mtime, :atime
|
101
95
|
|
102
|
-
def blocks
|
96
|
+
def blocks
|
97
|
+
nil
|
98
|
+
end
|
103
99
|
|
104
100
|
def get_entry
|
105
101
|
@zipFsFile.__send__(:get_entry, @entryName)
|
@@ -108,8 +104,8 @@ module Zip
|
|
108
104
|
|
109
105
|
def gid
|
110
106
|
e = get_entry
|
111
|
-
if e.extra.member?
|
112
|
-
e.extra[
|
107
|
+
if e.extra.member? 'IUnix'
|
108
|
+
e.extra['IUnix'].gid || 0
|
113
109
|
else
|
114
110
|
0
|
115
111
|
end
|
@@ -117,43 +113,57 @@ module Zip
|
|
117
113
|
|
118
114
|
def uid
|
119
115
|
e = get_entry
|
120
|
-
if e.extra.member?
|
121
|
-
e.extra[
|
116
|
+
if e.extra.member? 'IUnix'
|
117
|
+
e.extra['IUnix'].uid || 0
|
122
118
|
else
|
123
119
|
0
|
124
120
|
end
|
125
121
|
end
|
126
122
|
|
127
|
-
def ino
|
123
|
+
def ino
|
124
|
+
0
|
125
|
+
end
|
128
126
|
|
129
|
-
def dev
|
127
|
+
def dev
|
128
|
+
0
|
129
|
+
end
|
130
130
|
|
131
|
-
def rdev
|
131
|
+
def rdev
|
132
|
+
0
|
133
|
+
end
|
132
134
|
|
133
|
-
def rdev_major
|
135
|
+
def rdev_major
|
136
|
+
0
|
137
|
+
end
|
134
138
|
|
135
|
-
def rdev_minor
|
139
|
+
def rdev_minor
|
140
|
+
0
|
141
|
+
end
|
136
142
|
|
137
143
|
def ftype
|
138
144
|
if file?
|
139
|
-
|
145
|
+
'file'
|
140
146
|
elsif directory?
|
141
|
-
|
147
|
+
'directory'
|
142
148
|
else
|
143
|
-
raise StandardError,
|
149
|
+
raise StandardError, 'Unknown file type'
|
144
150
|
end
|
145
151
|
end
|
146
152
|
|
147
|
-
def nlink
|
153
|
+
def nlink
|
154
|
+
1
|
155
|
+
end
|
148
156
|
|
149
|
-
def blksize
|
157
|
+
def blksize
|
158
|
+
nil
|
159
|
+
end
|
150
160
|
|
151
161
|
def mode
|
152
162
|
e = get_entry
|
153
163
|
if e.fstype == 3
|
154
|
-
e.
|
164
|
+
e.external_file_attributes >> 16
|
155
165
|
else
|
156
|
-
|
166
|
+
33_206 # 33206 is equivalent to -rw-rw-rw-
|
157
167
|
end
|
158
168
|
end
|
159
169
|
end
|
@@ -163,7 +173,7 @@ module Zip
|
|
163
173
|
end
|
164
174
|
|
165
175
|
def get_entry(fileName)
|
166
|
-
|
176
|
+
unless exists?(fileName)
|
167
177
|
raise Errno::ENOENT, "No such file or directory - #{fileName}"
|
168
178
|
end
|
169
179
|
@mappedZip.find_entry(fileName)
|
@@ -171,77 +181,75 @@ module Zip
|
|
171
181
|
private :get_entry
|
172
182
|
|
173
183
|
def unix_mode_cmp(fileName, mode)
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
false
|
179
|
-
end
|
184
|
+
e = get_entry(fileName)
|
185
|
+
e.fstype == 3 && ((e.external_file_attributes >> 16) & mode) != 0
|
186
|
+
rescue Errno::ENOENT
|
187
|
+
false
|
180
188
|
end
|
181
189
|
private :unix_mode_cmp
|
182
190
|
|
183
191
|
def exists?(fileName)
|
184
|
-
expand_path(fileName) ==
|
192
|
+
expand_path(fileName) == '/' || !@mappedZip.find_entry(fileName).nil?
|
185
193
|
end
|
186
|
-
alias
|
194
|
+
alias exist? exists?
|
187
195
|
|
188
196
|
# Permissions not implemented, so if the file exists it is accessible
|
189
|
-
alias owned?
|
190
|
-
alias grpowned?
|
197
|
+
alias owned? exists?
|
198
|
+
alias grpowned? exists?
|
191
199
|
|
192
200
|
def readable?(fileName)
|
193
|
-
unix_mode_cmp(fileName,
|
201
|
+
unix_mode_cmp(fileName, 0o444)
|
194
202
|
end
|
195
|
-
alias readable_real?
|
203
|
+
alias readable_real? readable?
|
196
204
|
|
197
205
|
def writable?(fileName)
|
198
|
-
unix_mode_cmp(fileName,
|
206
|
+
unix_mode_cmp(fileName, 0o222)
|
199
207
|
end
|
200
|
-
alias writable_real?
|
208
|
+
alias writable_real? writable?
|
201
209
|
|
202
210
|
def executable?(fileName)
|
203
|
-
unix_mode_cmp(fileName,
|
211
|
+
unix_mode_cmp(fileName, 0o111)
|
204
212
|
end
|
205
213
|
alias executable_real? executable?
|
206
214
|
|
207
215
|
def setuid?(fileName)
|
208
|
-
unix_mode_cmp(fileName,
|
216
|
+
unix_mode_cmp(fileName, 0o4000)
|
209
217
|
end
|
210
218
|
|
211
219
|
def setgid?(fileName)
|
212
|
-
unix_mode_cmp(fileName,
|
220
|
+
unix_mode_cmp(fileName, 0o2000)
|
213
221
|
end
|
214
222
|
|
215
223
|
def sticky?(fileName)
|
216
|
-
unix_mode_cmp(fileName,
|
224
|
+
unix_mode_cmp(fileName, 0o1000)
|
217
225
|
end
|
218
226
|
|
219
227
|
def umask(*args)
|
220
228
|
::File.umask(*args)
|
221
229
|
end
|
222
230
|
|
223
|
-
def truncate(
|
224
|
-
raise StandardError,
|
231
|
+
def truncate(_fileName, _len)
|
232
|
+
raise StandardError, 'truncate not supported'
|
225
233
|
end
|
226
234
|
|
227
235
|
def directory?(fileName)
|
228
236
|
entry = @mappedZip.find_entry(fileName)
|
229
|
-
expand_path(fileName) ==
|
237
|
+
expand_path(fileName) == '/' || (!entry.nil? && entry.directory?)
|
230
238
|
end
|
231
239
|
|
232
|
-
def open(fileName, openMode =
|
233
|
-
openMode.
|
240
|
+
def open(fileName, openMode = 'r', permissionInt = 0o644, &block)
|
241
|
+
openMode.delete!('b') # ignore b option
|
234
242
|
case openMode
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
243
|
+
when 'r'
|
244
|
+
@mappedZip.get_input_stream(fileName, &block)
|
245
|
+
when 'w'
|
246
|
+
@mappedZip.get_output_stream(fileName, permissionInt, &block)
|
247
|
+
else
|
248
|
+
raise StandardError, "openmode '#{openMode} not supported" unless openMode == 'r'
|
241
249
|
end
|
242
250
|
end
|
243
251
|
|
244
|
-
def new(fileName, openMode =
|
252
|
+
def new(fileName, openMode = 'r')
|
245
253
|
open(fileName, openMode)
|
246
254
|
end
|
247
255
|
|
@@ -252,43 +260,41 @@ module Zip
|
|
252
260
|
# Returns nil for not found and nil for directories
|
253
261
|
def size?(fileName)
|
254
262
|
entry = @mappedZip.find_entry(fileName)
|
255
|
-
|
263
|
+
entry.nil? || entry.directory? ? nil : entry.size
|
256
264
|
end
|
257
265
|
|
258
266
|
def chown(ownerInt, groupInt, *filenames)
|
259
|
-
filenames.each
|
267
|
+
filenames.each do |fileName|
|
260
268
|
e = get_entry(fileName)
|
261
|
-
unless e.extra.member?(
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
e.extra["IUnix"].gid = groupInt
|
266
|
-
}
|
269
|
+
e.extra.create('IUnix') unless e.extra.member?('IUnix')
|
270
|
+
e.extra['IUnix'].uid = ownerInt
|
271
|
+
e.extra['IUnix'].gid = groupInt
|
272
|
+
end
|
267
273
|
filenames.size
|
268
274
|
end
|
269
275
|
|
270
|
-
def chmod
|
271
|
-
filenames.each
|
276
|
+
def chmod(modeInt, *filenames)
|
277
|
+
filenames.each do |fileName|
|
272
278
|
e = get_entry(fileName)
|
273
279
|
e.fstype = 3 # force convertion filesystem type to unix
|
274
280
|
e.unix_perms = modeInt
|
275
|
-
e.
|
281
|
+
e.external_file_attributes = modeInt << 16
|
276
282
|
e.dirty = true
|
277
|
-
|
283
|
+
end
|
278
284
|
filenames.size
|
279
285
|
end
|
280
286
|
|
281
287
|
def zero?(fileName)
|
282
288
|
sz = size(fileName)
|
283
|
-
sz
|
289
|
+
sz.nil? || sz == 0
|
284
290
|
rescue Errno::ENOENT
|
285
291
|
false
|
286
292
|
end
|
287
293
|
|
288
294
|
def file?(fileName)
|
289
295
|
entry = @mappedZip.find_entry(fileName)
|
290
|
-
entry
|
291
|
-
end
|
296
|
+
!entry.nil? && entry.file?
|
297
|
+
end
|
292
298
|
|
293
299
|
def dirname(fileName)
|
294
300
|
::File.dirname(fileName)
|
@@ -307,9 +313,9 @@ module Zip
|
|
307
313
|
end
|
308
314
|
|
309
315
|
def utime(modifiedTime, *fileNames)
|
310
|
-
fileNames.each
|
316
|
+
fileNames.each do |fileName|
|
311
317
|
get_entry(fileName).time = modifiedTime
|
312
|
-
|
318
|
+
end
|
313
319
|
end
|
314
320
|
|
315
321
|
def mtime(fileName)
|
@@ -318,66 +324,64 @@ module Zip
|
|
318
324
|
|
319
325
|
def atime(fileName)
|
320
326
|
e = get_entry(fileName)
|
321
|
-
if e.extra.member?
|
322
|
-
e.extra[
|
323
|
-
|
324
|
-
|
327
|
+
if e.extra.member? 'UniversalTime'
|
328
|
+
e.extra['UniversalTime'].atime
|
329
|
+
elsif e.extra.member? 'NTFS'
|
330
|
+
e.extra['NTFS'].atime
|
325
331
|
end
|
326
332
|
end
|
327
333
|
|
328
334
|
def ctime(fileName)
|
329
335
|
e = get_entry(fileName)
|
330
|
-
if e.extra.member?
|
331
|
-
e.extra[
|
332
|
-
|
333
|
-
|
336
|
+
if e.extra.member? 'UniversalTime'
|
337
|
+
e.extra['UniversalTime'].ctime
|
338
|
+
elsif e.extra.member? 'NTFS'
|
339
|
+
e.extra['NTFS'].ctime
|
334
340
|
end
|
335
341
|
end
|
336
342
|
|
337
|
-
def pipe?(
|
343
|
+
def pipe?(_filename)
|
338
344
|
false
|
339
345
|
end
|
340
346
|
|
341
|
-
def blockdev?(
|
347
|
+
def blockdev?(_filename)
|
342
348
|
false
|
343
349
|
end
|
344
350
|
|
345
|
-
def chardev?(
|
351
|
+
def chardev?(_filename)
|
346
352
|
false
|
347
353
|
end
|
348
354
|
|
349
|
-
def symlink?(
|
355
|
+
def symlink?(_fileName)
|
350
356
|
false
|
351
357
|
end
|
352
358
|
|
353
|
-
def socket?(
|
359
|
+
def socket?(_fileName)
|
354
360
|
false
|
355
361
|
end
|
356
362
|
|
357
363
|
def ftype(fileName)
|
358
|
-
@mappedZip.get_entry(fileName).directory? ?
|
364
|
+
@mappedZip.get_entry(fileName).directory? ? 'directory' : 'file'
|
359
365
|
end
|
360
366
|
|
361
|
-
def readlink(
|
362
|
-
raise NotImplementedError,
|
367
|
+
def readlink(_fileName)
|
368
|
+
raise NotImplementedError, 'The readlink() function is not implemented'
|
363
369
|
end
|
364
370
|
|
365
|
-
def symlink(
|
366
|
-
raise NotImplementedError,
|
371
|
+
def symlink(_fileName, _symlinkName)
|
372
|
+
raise NotImplementedError, 'The symlink() function is not implemented'
|
367
373
|
end
|
368
374
|
|
369
|
-
def link(
|
370
|
-
raise NotImplementedError,
|
375
|
+
def link(_fileName, _symlinkName)
|
376
|
+
raise NotImplementedError, 'The link() function is not implemented'
|
371
377
|
end
|
372
378
|
|
373
379
|
def pipe
|
374
|
-
raise NotImplementedError,
|
380
|
+
raise NotImplementedError, 'The pipe() function is not implemented'
|
375
381
|
end
|
376
382
|
|
377
383
|
def stat(fileName)
|
378
|
-
|
379
|
-
raise Errno::ENOENT, fileName
|
380
|
-
end
|
384
|
+
raise Errno::ENOENT, fileName unless exists?(fileName)
|
381
385
|
ZipFsStat.new(self, fileName)
|
382
386
|
end
|
383
387
|
|
@@ -392,7 +396,7 @@ module Zip
|
|
392
396
|
end
|
393
397
|
|
394
398
|
def popen(*args, &aProc)
|
395
|
-
File.popen(*args, &aProc)
|
399
|
+
::File.popen(*args, &aProc)
|
396
400
|
end
|
397
401
|
|
398
402
|
def foreach(fileName, aSep = $/, &aProc)
|
@@ -400,20 +404,19 @@ module Zip
|
|
400
404
|
end
|
401
405
|
|
402
406
|
def delete(*args)
|
403
|
-
args.each
|
404
|
-
|fileName|
|
407
|
+
args.each do |fileName|
|
405
408
|
if directory?(fileName)
|
406
409
|
raise Errno::EISDIR, "Is a directory - \"#{fileName}\""
|
407
410
|
end
|
408
411
|
@mappedZip.remove(fileName)
|
409
|
-
|
412
|
+
end
|
410
413
|
end
|
411
414
|
|
412
415
|
def rename(fileToRename, newName)
|
413
416
|
@mappedZip.rename(fileToRename, newName) { true }
|
414
417
|
end
|
415
418
|
|
416
|
-
alias
|
419
|
+
alias unlink delete
|
417
420
|
|
418
421
|
def expand_path(aPath)
|
419
422
|
@mappedZip.expand_path(aPath)
|
@@ -427,7 +430,6 @@ module Zip
|
|
427
430
|
# The individual methods are not documented due to their
|
428
431
|
# similarity with the methods in Dir
|
429
432
|
class ZipFsDir
|
430
|
-
|
431
433
|
def initialize(mappedZip)
|
432
434
|
@mappedZip = mappedZip
|
433
435
|
end
|
@@ -451,7 +453,9 @@ module Zip
|
|
451
453
|
dirIt
|
452
454
|
end
|
453
455
|
|
454
|
-
def pwd
|
456
|
+
def pwd
|
457
|
+
@mappedZip.pwd
|
458
|
+
end
|
455
459
|
alias getwd pwd
|
456
460
|
|
457
461
|
def chdir(aDirectoryName)
|
@@ -467,8 +471,8 @@ module Zip
|
|
467
471
|
entries
|
468
472
|
end
|
469
473
|
|
470
|
-
def glob(*args
|
471
|
-
@mappedZip.glob(*args
|
474
|
+
def glob(*args, &block)
|
475
|
+
@mappedZip.glob(*args, &block)
|
472
476
|
end
|
473
477
|
|
474
478
|
def foreach(aDirectoryName)
|
@@ -479,11 +483,10 @@ module Zip
|
|
479
483
|
path << '/' unless path.end_with?('/')
|
480
484
|
path = Regexp.escape(path)
|
481
485
|
subDirEntriesRegex = Regexp.new("^#{path}([^/]+)$")
|
482
|
-
@mappedZip.each
|
483
|
-
|fileName|
|
486
|
+
@mappedZip.each do |fileName|
|
484
487
|
match = subDirEntriesRegex.match(fileName)
|
485
|
-
yield(match[1]) unless match
|
486
|
-
|
488
|
+
yield(match[1]) unless match.nil?
|
489
|
+
end
|
487
490
|
end
|
488
491
|
|
489
492
|
def delete(entryName)
|
@@ -492,17 +495,16 @@ module Zip
|
|
492
495
|
end
|
493
496
|
@mappedZip.remove(entryName)
|
494
497
|
end
|
495
|
-
alias rmdir
|
498
|
+
alias rmdir delete
|
496
499
|
alias unlink delete
|
497
500
|
|
498
|
-
def mkdir(entryName, permissionInt =
|
501
|
+
def mkdir(entryName, permissionInt = 0o755)
|
499
502
|
@mappedZip.mkdir(entryName, permissionInt)
|
500
503
|
end
|
501
504
|
|
502
|
-
def chroot(*
|
503
|
-
raise NotImplementedError,
|
505
|
+
def chroot(*_args)
|
506
|
+
raise NotImplementedError, 'The chroot() function is not implemented'
|
504
507
|
end
|
505
|
-
|
506
508
|
end
|
507
509
|
|
508
510
|
class ZipFsDirIterator # :nodoc:all
|
@@ -518,39 +520,39 @@ module Zip
|
|
518
520
|
end
|
519
521
|
|
520
522
|
def each(&aProc)
|
521
|
-
raise IOError,
|
523
|
+
raise IOError, 'closed directory' if @fileNames.nil?
|
522
524
|
@fileNames.each(&aProc)
|
523
525
|
end
|
524
526
|
|
525
527
|
def read
|
526
|
-
raise IOError,
|
527
|
-
@fileNames[(@index+=1)-1]
|
528
|
+
raise IOError, 'closed directory' if @fileNames.nil?
|
529
|
+
@fileNames[(@index += 1) - 1]
|
528
530
|
end
|
529
531
|
|
530
532
|
def rewind
|
531
|
-
raise IOError,
|
533
|
+
raise IOError, 'closed directory' if @fileNames.nil?
|
532
534
|
@index = 0
|
533
535
|
end
|
534
536
|
|
535
537
|
def seek(anIntegerPosition)
|
536
|
-
raise IOError,
|
538
|
+
raise IOError, 'closed directory' if @fileNames.nil?
|
537
539
|
@index = anIntegerPosition
|
538
540
|
end
|
539
541
|
|
540
542
|
def tell
|
541
|
-
raise IOError,
|
543
|
+
raise IOError, 'closed directory' if @fileNames.nil?
|
542
544
|
@index
|
543
545
|
end
|
544
546
|
end
|
545
547
|
|
546
|
-
# All access to
|
548
|
+
# All access to Zip::File from ZipFsFile and ZipFsDir goes through a
|
547
549
|
# ZipFileNameMapper, which has one responsibility: ensure
|
548
550
|
class ZipFileNameMapper # :nodoc:all
|
549
551
|
include Enumerable
|
550
552
|
|
551
553
|
def initialize(zipFile)
|
552
554
|
@zipFile = zipFile
|
553
|
-
@pwd =
|
555
|
+
@pwd = '/'
|
554
556
|
end
|
555
557
|
|
556
558
|
attr_accessor :pwd
|
@@ -571,6 +573,10 @@ module Zip
|
|
571
573
|
@zipFile.get_output_stream(expand_to_entry(fileName), permissionInt, &aProc)
|
572
574
|
end
|
573
575
|
|
576
|
+
def glob(pattern, *flags, &block)
|
577
|
+
@zipFile.glob(expand_to_entry(pattern), *flags, &block)
|
578
|
+
end
|
579
|
+
|
574
580
|
def read(fileName)
|
575
581
|
@zipFile.read(expand_to_entry(fileName))
|
576
582
|
end
|
@@ -580,28 +586,27 @@ module Zip
|
|
580
586
|
end
|
581
587
|
|
582
588
|
def rename(fileName, newName, &continueOnExistsProc)
|
583
|
-
@zipFile.rename(expand_to_entry(fileName), expand_to_entry(newName),
|
589
|
+
@zipFile.rename(expand_to_entry(fileName), expand_to_entry(newName),
|
584
590
|
&continueOnExistsProc)
|
585
591
|
end
|
586
592
|
|
587
|
-
def mkdir(fileName, permissionInt =
|
593
|
+
def mkdir(fileName, permissionInt = 0o755)
|
588
594
|
@zipFile.mkdir(expand_to_entry(fileName), permissionInt)
|
589
595
|
end
|
590
596
|
|
591
597
|
# Turns entries into strings and adds leading /
|
592
598
|
# and removes trailing slash on directories
|
593
599
|
def each
|
594
|
-
@zipFile.each
|
595
|
-
|
596
|
-
|
597
|
-
}
|
600
|
+
@zipFile.each do |e|
|
601
|
+
yield('/' + e.to_s.chomp('/'))
|
602
|
+
end
|
598
603
|
end
|
599
604
|
|
600
605
|
def expand_path(aPath)
|
601
|
-
expanded = aPath.start_with?(
|
602
|
-
expanded.gsub!(/\/\.(\/|$)/,
|
603
|
-
expanded.gsub!(/[^\/]+\/\.\.(\/|$)/,
|
604
|
-
expanded.empty? ?
|
606
|
+
expanded = aPath.start_with?('/') ? aPath : ::File.join(@pwd, aPath)
|
607
|
+
expanded.gsub!(/\/\.(\/|$)/, '')
|
608
|
+
expanded.gsub!(/[^\/]+\/\.\.(\/|$)/, '')
|
609
|
+
expanded.empty? ? '/' : expanded
|
605
610
|
end
|
606
611
|
|
607
612
|
private
|
@@ -612,8 +617,8 @@ module Zip
|
|
612
617
|
end
|
613
618
|
end
|
614
619
|
|
615
|
-
class
|
616
|
-
include
|
620
|
+
class File
|
621
|
+
include FileSystem
|
617
622
|
end
|
618
623
|
end
|
619
624
|
|