Filename | /home/micha/.plenv/versions/5.38.2/lib/perl5/site_perl/5.38.2/Archive/Zip/ZipFileMember.pm |
Statements | Executed 625 statements in 1.39ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
10 | 1 | 1 | 98µs | 178µs | _readCentralDirectoryFileHeader | Archive::Zip::ZipFileMember::
7 | 1 | 1 | 91µs | 1.85ms | rewindData | Archive::Zip::ZipFileMember::
7 | 1 | 1 | 72µs | 162µs | _skipLocalFileHeader | Archive::Zip::ZipFileMember::
7 | 1 | 1 | 61µs | 193µs | _seekToLocalHeader | Archive::Zip::ZipFileMember::
11 | 1 | 1 | 37µs | 247µs | _newFromZipFile | Archive::Zip::ZipFileMember::
21 | 2 | 2 | 28µs | 42µs | isDirectory | Archive::Zip::ZipFileMember::
7 | 1 | 1 | 22µs | 591µs | _readRawChunk | Archive::Zip::ZipFileMember::
1 | 1 | 1 | 10µs | 12µs | BEGIN@3 | Archive::Zip::ZipFileMember::
1 | 1 | 1 | 9µs | 178µs | BEGIN@11 | Archive::Zip::ZipFileMember::
1 | 1 | 1 | 7µs | 7µs | BEGIN@6 | Archive::Zip::ZipFileMember::
7 | 1 | 1 | 4µs | 4µs | dataOffset | Archive::Zip::ZipFileMember::
7 | 1 | 1 | 4µs | 4µs | localHeaderRelativeOffset | Archive::Zip::ZipFileMember::
1 | 1 | 1 | 3µs | 21µs | BEGIN@4 | Archive::Zip::ZipFileMember::
0 | 0 | 0 | 0s | 0s | _become | Archive::Zip::ZipFileMember::
0 | 0 | 0 | 0s | 0s | _readDataDescriptor | Archive::Zip::ZipFileMember::
0 | 0 | 0 | 0s | 0s | _readLocalFileHeader | Archive::Zip::ZipFileMember::
0 | 0 | 0 | 0s | 0s | diskNumberStart | Archive::Zip::ZipFileMember::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package Archive::Zip::ZipFileMember; | ||||
2 | |||||
3 | 2 | 21µs | 2 | 13µs | # spent 12µs (10+2) within Archive::Zip::ZipFileMember::BEGIN@3 which was called:
# once (10µs+2µs) by Spreadsheet::ParseXLSX::BEGIN@11 at line 3 # spent 12µs making 1 call to Archive::Zip::ZipFileMember::BEGIN@3
# spent 2µs making 1 call to strict::import |
4 | 2 | 22µs | 2 | 38µs | # spent 21µs (3+17) within Archive::Zip::ZipFileMember::BEGIN@4 which was called:
# once (3µs+17µs) by Spreadsheet::ParseXLSX::BEGIN@11 at line 4 # spent 21µs making 1 call to Archive::Zip::ZipFileMember::BEGIN@4
# spent 17µs making 1 call to vars::import |
5 | |||||
6 | # spent 7µs within Archive::Zip::ZipFileMember::BEGIN@6 which was called:
# once (7µs+0s) by Spreadsheet::ParseXLSX::BEGIN@11 at line 9 | ||||
7 | 1 | 200ns | $VERSION = '1.68'; | ||
8 | 1 | 7µs | @ISA = qw ( Archive::Zip::FileMember ); | ||
9 | 1 | 15µs | 1 | 7µs | } # spent 7µs making 1 call to Archive::Zip::ZipFileMember::BEGIN@6 |
10 | |||||
11 | 1 | 2µs | 1 | 169µs | # spent 178µs (9+169) within Archive::Zip::ZipFileMember::BEGIN@11 which was called:
# once (9µs+169µs) by Spreadsheet::ParseXLSX::BEGIN@11 at line 16 # spent 169µs making 1 call to Exporter::import |
12 | :CONSTANTS | ||||
13 | :ERROR_CODES | ||||
14 | :PKZIP_CONSTANTS | ||||
15 | :UTILITY_METHODS | ||||
16 | 1 | 968µs | 1 | 178µs | ); # spent 178µs making 1 call to Archive::Zip::ZipFileMember::BEGIN@11 |
17 | |||||
18 | # Create a new Archive::Zip::ZipFileMember | ||||
19 | # given a filename and optional open file handle | ||||
20 | # | ||||
21 | # spent 247µs (37+210) within Archive::Zip::ZipFileMember::_newFromZipFile which was called 11 times, avg 22µs/call:
# 11 times (37µs+210µs) by Archive::Zip::Member::_newFromZipFile at line 47 of Archive/Zip/Member.pm, avg 22µs/call | ||||
22 | 11 | 1µs | my $class = shift; | ||
23 | 11 | 1µs | my $fh = shift; | ||
24 | 11 | 2µs | my $externalFileName = shift; | ||
25 | 11 | 2µs | my $archiveZip64 = @_ ? shift : 0; | ||
26 | 11 | 1µs | my $possibleEocdOffset = @_ ? shift : 0; # normally 0 | ||
27 | |||||
28 | 11 | 10µs | 11 | 210µs | my $self = $class->new( # spent 210µs making 11 calls to Archive::Zip::Member::new, avg 19µs/call |
29 | 'eocdCrc32' => 0, | ||||
30 | 'diskNumberStart' => 0, | ||||
31 | 'localHeaderRelativeOffset' => 0, | ||||
32 | 'dataOffset' => 0, # localHeaderRelativeOffset + header length | ||||
33 | @_ | ||||
34 | ); | ||||
35 | 11 | 3µs | $self->{'externalFileName'} = $externalFileName; | ||
36 | 11 | 2µs | $self->{'fh'} = $fh; | ||
37 | 11 | 2µs | $self->{'archiveZip64'} = $archiveZip64; | ||
38 | 11 | 2µs | $self->{'possibleEocdOffset'} = $possibleEocdOffset; | ||
39 | 11 | 9µs | return $self; | ||
40 | } | ||||
41 | |||||
42 | # spent 42µs (28+13) within Archive::Zip::ZipFileMember::isDirectory which was called 21 times, avg 2µs/call:
# 11 times (15µs+7µs) by Archive::Zip::Member::unixFileAttributes at line 399 of Archive/Zip/Member.pm, avg 2µs/call
# 10 times (13µs+7µs) by Archive::Zip::Archive::readFromFileHandle at line 797 of Archive/Zip/Archive.pm, avg 2µs/call | ||||
43 | 21 | 2µs | my $self = shift; | ||
44 | 21 | 28µs | 21 | 13µs | return (substr($self->fileName, -1, 1) eq '/' # spent 13µs making 21 calls to Archive::Zip::Member::fileName, avg 633ns/call |
45 | and $self->uncompressedSize == 0); | ||||
46 | } | ||||
47 | |||||
48 | # Seek to the beginning of the local header, just past the signature. | ||||
49 | # Verify that the local header signature is in fact correct. | ||||
50 | # Update the localHeaderRelativeOffset if necessary by adding the possibleEocdOffset. | ||||
51 | # Returns status. | ||||
52 | |||||
53 | # spent 193µs (61+132) within Archive::Zip::ZipFileMember::_seekToLocalHeader which was called 7 times, avg 28µs/call:
# 7 times (61µs+132µs) by Archive::Zip::ZipFileMember::rewindData at line 450, avg 28µs/call | ||||
54 | 7 | 700ns | my $self = shift; | ||
55 | 7 | 1µs | my $where = shift; # optional | ||
56 | 7 | 500ns | my $previousWhere = shift; # optional | ||
57 | |||||
58 | 7 | 7µs | 7 | 4µs | $where = $self->localHeaderRelativeOffset() unless defined($where); # spent 4µs making 7 calls to Archive::Zip::ZipFileMember::localHeaderRelativeOffset, avg 500ns/call |
59 | |||||
60 | # avoid loop on certain corrupt files (from Julian Field) | ||||
61 | 7 | 2µs | return _formatError("corrupt zip file") | ||
62 | if defined($previousWhere) && $where == $previousWhere; | ||||
63 | |||||
64 | 7 | 1µs | my $status; | ||
65 | my $signature; | ||||
66 | |||||
67 | 7 | 9µs | 14 | 31µs | $status = $self->fh()->seek($where, IO::Seekable::SEEK_SET); # spent 20µs making 7 calls to IO::Seekable::seek, avg 3µs/call
# spent 11µs making 7 calls to Archive::Zip::FileMember::fh, avg 2µs/call |
68 | 7 | 1µs | return _ioError("seeking to local header") unless $status; | ||
69 | |||||
70 | 7 | 13µs | 21 | 97µs | ($status, $signature) = # spent 84µs making 7 calls to Archive::Zip::_readSignature, avg 12µs/call
# spent 10µs making 7 calls to Archive::Zip::FileMember::fh, avg 1µs/call
# spent 3µs making 7 calls to Archive::Zip::FileMember::externalFileName, avg 429ns/call |
71 | _readSignature($self->fh(), $self->externalFileName(), | ||||
72 | LOCAL_FILE_HEADER_SIGNATURE, 1); | ||||
73 | 7 | 1µs | return $status if $status == AZ_IO_ERROR; | ||
74 | |||||
75 | # retry with EOCD offset if any was given. | ||||
76 | 7 | 1µs | if ($status == AZ_FORMAT_ERROR && $self->{'possibleEocdOffset'}) { | ||
77 | $status = $self->_seekToLocalHeader( | ||||
78 | $self->localHeaderRelativeOffset() + $self->{'possibleEocdOffset'}, | ||||
79 | $where | ||||
80 | ); | ||||
81 | if ($status == AZ_OK) { | ||||
82 | $self->{'localHeaderRelativeOffset'} += | ||||
83 | $self->{'possibleEocdOffset'}; | ||||
84 | $self->{'possibleEocdOffset'} = 0; | ||||
85 | } | ||||
86 | } | ||||
87 | |||||
88 | 7 | 8µs | return $status; | ||
89 | } | ||||
90 | |||||
91 | # Because I'm going to delete the file handle, read the local file | ||||
92 | # header if the file handle is seekable. If it is not, I assume that | ||||
93 | # I've already read the local header. | ||||
94 | # Return ( $status, $self ) | ||||
95 | |||||
96 | sub _become { | ||||
97 | my $self = shift; | ||||
98 | my $newClass = shift; | ||||
99 | return $self if ref($self) eq $newClass; | ||||
100 | |||||
101 | my $status = AZ_OK; | ||||
102 | |||||
103 | if (_isSeekable($self->fh())) { | ||||
104 | my $here = $self->fh()->tell(); | ||||
105 | $status = $self->_seekToLocalHeader(); | ||||
106 | $status = $self->_readLocalFileHeader() if $status == AZ_OK; | ||||
107 | $self->fh()->seek($here, IO::Seekable::SEEK_SET); | ||||
108 | return $status unless $status == AZ_OK; | ||||
109 | } | ||||
110 | |||||
111 | delete($self->{'eocdCrc32'}); | ||||
112 | delete($self->{'diskNumberStart'}); | ||||
113 | delete($self->{'localHeaderRelativeOffset'}); | ||||
114 | delete($self->{'dataOffset'}); | ||||
115 | delete($self->{'archiveZip64'}); | ||||
116 | delete($self->{'possibleEocdOffset'}); | ||||
117 | |||||
118 | return $self->SUPER::_become($newClass); | ||||
119 | } | ||||
120 | |||||
121 | sub diskNumberStart { | ||||
122 | shift->{'diskNumberStart'}; | ||||
123 | } | ||||
124 | |||||
125 | # spent 4µs within Archive::Zip::ZipFileMember::localHeaderRelativeOffset which was called 7 times, avg 500ns/call:
# 7 times (4µs+0s) by Archive::Zip::ZipFileMember::_seekToLocalHeader at line 58, avg 500ns/call | ||||
126 | 7 | 7µs | shift->{'localHeaderRelativeOffset'}; | ||
127 | } | ||||
128 | |||||
129 | # spent 4µs within Archive::Zip::ZipFileMember::dataOffset which was called 7 times, avg 557ns/call:
# 7 times (4µs+0s) by Archive::Zip::ZipFileMember::rewindData at line 458, avg 557ns/call | ||||
130 | 7 | 7µs | shift->{'dataOffset'}; | ||
131 | } | ||||
132 | |||||
133 | # Skip local file header, updating only extra field stuff. | ||||
134 | # Assumes that fh is positioned before signature. | ||||
135 | # spent 162µs (72+89) within Archive::Zip::ZipFileMember::_skipLocalFileHeader which was called 7 times, avg 23µs/call:
# 7 times (72µs+89µs) by Archive::Zip::ZipFileMember::rewindData at line 454, avg 23µs/call | ||||
136 | 7 | 800ns | my $self = shift; | ||
137 | 7 | 500ns | my $header; | ||
138 | 7 | 7µs | 14 | 22µs | my $bytesRead = $self->fh()->read($header, LOCAL_FILE_HEADER_LENGTH); # spent 13µs making 7 calls to Archive::Zip::FileMember::fh, avg 2µs/call
# spent 9µs making 7 calls to IO::Handle::read, avg 1µs/call |
139 | 7 | 1µs | if ($bytesRead != LOCAL_FILE_HEADER_LENGTH) { | ||
140 | return _ioError("reading local file header"); | ||||
141 | } | ||||
142 | 7 | 1µs | my $fileNameLength; | ||
143 | my $extraFieldLength; | ||||
144 | my $bitFlag; | ||||
145 | ( | ||||
146 | undef, # $self->{'versionNeededToExtract'}, | ||||
147 | 7 | 15µs | 7 | 5µs | $bitFlag, # spent 5µs making 7 calls to CORE::unpack, avg 657ns/call |
148 | undef, # $self->{'compressionMethod'}, | ||||
149 | undef, # $self->{'lastModFileDateTime'}, | ||||
150 | undef, # $crc32, | ||||
151 | undef, # $compressedSize, | ||||
152 | undef, # $uncompressedSize, | ||||
153 | $fileNameLength, | ||||
154 | $extraFieldLength | ||||
155 | ) = unpack(LOCAL_FILE_HEADER_FORMAT, $header); | ||||
156 | |||||
157 | 7 | 8µs | 14 | 34µs | if ($fileNameLength) { # spent 23µs making 7 calls to IO::Seekable::seek, avg 3µs/call
# spent 11µs making 7 calls to Archive::Zip::FileMember::fh, avg 2µs/call |
158 | $self->fh()->seek($fileNameLength, IO::Seekable::SEEK_CUR) | ||||
159 | or return _ioError("skipping local file name"); | ||||
160 | } | ||||
161 | |||||
162 | 7 | 1µs | my $zip64 = 0; | ||
163 | 7 | 1µs | if ($extraFieldLength) { | ||
164 | $bytesRead = | ||||
165 | 2 | 3µs | 4 | 9µs | $self->fh()->read($self->{'localExtraField'}, $extraFieldLength); # spent 6µs making 2 calls to IO::Handle::read, avg 3µs/call
# spent 3µs making 2 calls to Archive::Zip::FileMember::fh, avg 1µs/call |
166 | 2 | 1µs | if ($bytesRead != $extraFieldLength) { | ||
167 | return _ioError("reading local extra field"); | ||||
168 | } | ||||
169 | 2 | 700ns | if ($self->{'archiveZip64'}) { | ||
170 | my $status; | ||||
171 | ($status, $zip64) = | ||||
172 | $self->_extractZip64ExtraField($self->{'localExtraField'}, undef, undef); | ||||
173 | return $status if $status != AZ_OK; | ||||
174 | $self->{'zip64'} ||= $zip64; | ||||
175 | } | ||||
176 | } | ||||
177 | |||||
178 | 7 | 8µs | 14 | 20µs | $self->{'dataOffset'} = $self->fh()->tell(); # spent 10µs making 7 calls to Archive::Zip::FileMember::fh, avg 1µs/call
# spent 10µs making 7 calls to IO::Seekable::tell, avg 1µs/call |
179 | |||||
180 | 7 | 2µs | if ($bitFlag & GPBF_HAS_DATA_DESCRIPTOR_MASK) { | ||
181 | |||||
182 | # Read the crc32, compressedSize, and uncompressedSize from the | ||||
183 | # extended data descriptor, which directly follows the compressed data. | ||||
184 | # | ||||
185 | # Skip over the compressed file data (assumes that EOCD compressedSize | ||||
186 | # was correct) | ||||
187 | $self->fh()->seek($self->{'compressedSize'}, IO::Seekable::SEEK_CUR) | ||||
188 | or return _ioError("seeking to extended local header"); | ||||
189 | |||||
190 | # these values should be set correctly from before. | ||||
191 | my $oldCrc32 = $self->{'eocdCrc32'}; | ||||
192 | my $oldCompressedSize = $self->{'compressedSize'}; | ||||
193 | my $oldUncompressedSize = $self->{'uncompressedSize'}; | ||||
194 | |||||
195 | my $status = $self->_readDataDescriptor($zip64); | ||||
196 | return $status unless $status == AZ_OK; | ||||
197 | |||||
198 | # The buffer with encrypted data is prefixed with a new | ||||
199 | # encrypted 12 byte header. The size only changes when | ||||
200 | # the buffer is also compressed | ||||
201 | $self->isEncrypted && $oldUncompressedSize > $self->{'uncompressedSize'} | ||||
202 | and $oldUncompressedSize -= DATA_DESCRIPTOR_LENGTH; | ||||
203 | |||||
204 | return _formatError( | ||||
205 | "CRC or size mismatch while skipping data descriptor") | ||||
206 | if ( $oldCrc32 != $self->{'crc32'} | ||||
207 | || $oldUncompressedSize != $self->{'uncompressedSize'}); | ||||
208 | |||||
209 | $self->{'crc32'} = 0 | ||||
210 | if $self->compressionMethod() == COMPRESSION_STORED ; | ||||
211 | } | ||||
212 | |||||
213 | 7 | 8µs | return AZ_OK; | ||
214 | } | ||||
215 | |||||
216 | # Read from a local file header into myself. Returns AZ_OK (in | ||||
217 | # scalar context) or a pair (AZ_OK, $headerSize) (in list | ||||
218 | # context) if successful. | ||||
219 | # Assumes that fh is positioned after signature. | ||||
220 | # Note that crc32, compressedSize, and uncompressedSize will be 0 if | ||||
221 | # GPBF_HAS_DATA_DESCRIPTOR_MASK is set in the bitFlag. | ||||
222 | |||||
223 | sub _readLocalFileHeader { | ||||
224 | my $self = shift; | ||||
225 | my $header; | ||||
226 | my $bytesRead = $self->fh()->read($header, LOCAL_FILE_HEADER_LENGTH); | ||||
227 | if ($bytesRead != LOCAL_FILE_HEADER_LENGTH) { | ||||
228 | return _ioError("reading local file header"); | ||||
229 | } | ||||
230 | my $fileNameLength; | ||||
231 | my $crc32; | ||||
232 | my $compressedSize; | ||||
233 | my $uncompressedSize; | ||||
234 | my $extraFieldLength; | ||||
235 | ( | ||||
236 | $self->{'versionNeededToExtract'}, $self->{'bitFlag'}, | ||||
237 | $self->{'compressionMethod'}, $self->{'lastModFileDateTime'}, | ||||
238 | $crc32, $compressedSize, | ||||
239 | $uncompressedSize, $fileNameLength, | ||||
240 | $extraFieldLength | ||||
241 | ) = unpack(LOCAL_FILE_HEADER_FORMAT, $header); | ||||
242 | |||||
243 | if ($fileNameLength) { | ||||
244 | my $fileName; | ||||
245 | $bytesRead = $self->fh()->read($fileName, $fileNameLength); | ||||
246 | if ($bytesRead != $fileNameLength) { | ||||
247 | return _ioError("reading local file name"); | ||||
248 | } | ||||
249 | $self->fileName($fileName); | ||||
250 | } | ||||
251 | |||||
252 | my $zip64 = 0; | ||||
253 | if ($extraFieldLength) { | ||||
254 | $bytesRead = | ||||
255 | $self->fh()->read($self->{'localExtraField'}, $extraFieldLength); | ||||
256 | if ($bytesRead != $extraFieldLength) { | ||||
257 | return _ioError("reading local extra field"); | ||||
258 | } | ||||
259 | if ($self->{'archiveZip64'}) { | ||||
260 | my $status; | ||||
261 | ($status, $zip64) = | ||||
262 | $self->_extractZip64ExtraField($self->{'localExtraField'}, | ||||
263 | $uncompressedSize, | ||||
264 | $compressedSize); | ||||
265 | return $status if $status != AZ_OK; | ||||
266 | $self->{'zip64'} ||= $zip64; | ||||
267 | } | ||||
268 | } | ||||
269 | |||||
270 | $self->{'dataOffset'} = $self->fh()->tell(); | ||||
271 | |||||
272 | if ($self->hasDataDescriptor()) { | ||||
273 | |||||
274 | # Read the crc32, compressedSize, and uncompressedSize from the | ||||
275 | # extended data descriptor. | ||||
276 | # Skip over the compressed file data (assumes that EOCD compressedSize | ||||
277 | # was correct) | ||||
278 | $self->fh()->seek($self->{'compressedSize'}, IO::Seekable::SEEK_CUR) | ||||
279 | or return _ioError("seeking to extended local header"); | ||||
280 | |||||
281 | my $status = $self->_readDataDescriptor($zip64); | ||||
282 | return $status unless $status == AZ_OK; | ||||
283 | } else { | ||||
284 | return _formatError( | ||||
285 | "CRC or size mismatch after reading data descriptor") | ||||
286 | if ( $self->{'crc32'} != $crc32 | ||||
287 | || $self->{'uncompressedSize'} != $uncompressedSize); | ||||
288 | } | ||||
289 | |||||
290 | return | ||||
291 | wantarray | ||||
292 | ? (AZ_OK, | ||||
293 | SIGNATURE_LENGTH, | ||||
294 | LOCAL_FILE_HEADER_LENGTH + | ||||
295 | $fileNameLength + | ||||
296 | $extraFieldLength) | ||||
297 | : AZ_OK; | ||||
298 | } | ||||
299 | |||||
300 | # This will read the data descriptor, which is after the end of compressed file | ||||
301 | # data in members that have GPBF_HAS_DATA_DESCRIPTOR_MASK set in their bitFlag. | ||||
302 | # The only reliable way to find these is to rely on the EOCD compressedSize. | ||||
303 | # Assumes that file is positioned immediately after the compressed data. | ||||
304 | # Returns status; sets crc32, compressedSize, and uncompressedSize. | ||||
305 | sub _readDataDescriptor { | ||||
306 | my $self = shift; | ||||
307 | my $zip64 = shift; | ||||
308 | my $signatureData; | ||||
309 | my $header; | ||||
310 | my $crc32; | ||||
311 | my $compressedSize; | ||||
312 | my $uncompressedSize; | ||||
313 | |||||
314 | my $bytesRead = $self->fh()->read($signatureData, SIGNATURE_LENGTH); | ||||
315 | return _ioError("reading header signature") | ||||
316 | if $bytesRead != SIGNATURE_LENGTH; | ||||
317 | my $signature = unpack(SIGNATURE_FORMAT, $signatureData); | ||||
318 | |||||
319 | my $dataDescriptorLength; | ||||
320 | my $dataDescriptorFormat; | ||||
321 | my $dataDescriptorLengthNoSig; | ||||
322 | my $dataDescriptorFormatNoSig; | ||||
323 | if (! $zip64) { | ||||
324 | $dataDescriptorLength = DATA_DESCRIPTOR_LENGTH; | ||||
325 | $dataDescriptorFormat = DATA_DESCRIPTOR_FORMAT; | ||||
326 | $dataDescriptorLengthNoSig = DATA_DESCRIPTOR_LENGTH_NO_SIG; | ||||
327 | $dataDescriptorFormatNoSig = DATA_DESCRIPTOR_FORMAT_NO_SIG | ||||
328 | } | ||||
329 | else { | ||||
330 | $dataDescriptorLength = DATA_DESCRIPTOR_ZIP64_LENGTH; | ||||
331 | $dataDescriptorFormat = DATA_DESCRIPTOR_ZIP64_FORMAT; | ||||
332 | $dataDescriptorLengthNoSig = DATA_DESCRIPTOR_ZIP64_LENGTH_NO_SIG; | ||||
333 | $dataDescriptorFormatNoSig = DATA_DESCRIPTOR_ZIP64_FORMAT_NO_SIG | ||||
334 | } | ||||
335 | |||||
336 | # unfortunately, the signature appears to be optional. | ||||
337 | if ($signature == DATA_DESCRIPTOR_SIGNATURE | ||||
338 | && ($signature != $self->{'crc32'})) { | ||||
339 | $bytesRead = $self->fh()->read($header, $dataDescriptorLength); | ||||
340 | return _ioError("reading data descriptor") | ||||
341 | if $bytesRead != $dataDescriptorLength; | ||||
342 | |||||
343 | ($crc32, $compressedSize, $uncompressedSize) = | ||||
344 | unpack($dataDescriptorFormat, $header); | ||||
345 | } else { | ||||
346 | $bytesRead = $self->fh()->read($header, $dataDescriptorLengthNoSig); | ||||
347 | return _ioError("reading data descriptor") | ||||
348 | if $bytesRead != $dataDescriptorLengthNoSig; | ||||
349 | |||||
350 | $crc32 = $signature; | ||||
351 | ($compressedSize, $uncompressedSize) = | ||||
352 | unpack($dataDescriptorFormatNoSig, $header); | ||||
353 | } | ||||
354 | |||||
355 | $self->{'eocdCrc32'} = $self->{'crc32'} | ||||
356 | unless defined($self->{'eocdCrc32'}); | ||||
357 | $self->{'crc32'} = $crc32; | ||||
358 | $self->{'compressedSize'} = $compressedSize; | ||||
359 | $self->{'uncompressedSize'} = $uncompressedSize; | ||||
360 | |||||
361 | return AZ_OK; | ||||
362 | } | ||||
363 | |||||
364 | # Read a Central Directory header. Return AZ_OK on success. | ||||
365 | # Assumes that fh is positioned right after the signature. | ||||
366 | |||||
367 | # spent 178µs (98+80) within Archive::Zip::ZipFileMember::_readCentralDirectoryFileHeader which was called 10 times, avg 18µs/call:
# 10 times (98µs+80µs) by Archive::Zip::Archive::readFromFileHandle at line 792 of Archive/Zip/Archive.pm, avg 18µs/call | ||||
368 | 10 | 400ns | my $self = shift; | ||
369 | 10 | 6µs | 10 | 23µs | my $fh = $self->fh(); # spent 23µs making 10 calls to Archive::Zip::FileMember::fh, avg 2µs/call |
370 | 10 | 1µs | my $header = ''; | ||
371 | 10 | 5µs | 10 | 12µs | my $bytesRead = $fh->read($header, CENTRAL_DIRECTORY_FILE_HEADER_LENGTH); # spent 12µs making 10 calls to IO::Handle::read, avg 1µs/call |
372 | 10 | 1µs | if ($bytesRead != CENTRAL_DIRECTORY_FILE_HEADER_LENGTH) { | ||
373 | return _ioError("reading central dir header"); | ||||
374 | } | ||||
375 | 10 | 1µs | my ($fileNameLength, $extraFieldLength, $fileCommentLength); | ||
376 | ( | ||||
377 | $self->{'versionMadeBy'}, | ||||
378 | $self->{'fileAttributeFormat'}, | ||||
379 | $self->{'versionNeededToExtract'}, | ||||
380 | $self->{'bitFlag'}, | ||||
381 | $self->{'compressionMethod'}, | ||||
382 | $self->{'lastModFileDateTime'}, | ||||
383 | $self->{'crc32'}, | ||||
384 | $self->{'compressedSize'}, | ||||
385 | $self->{'uncompressedSize'}, | ||||
386 | $fileNameLength, | ||||
387 | $extraFieldLength, | ||||
388 | $fileCommentLength, | ||||
389 | $self->{'diskNumberStart'}, | ||||
390 | $self->{'internalFileAttributes'}, | ||||
391 | $self->{'externalFileAttributes'}, | ||||
392 | 10 | 25µs | 10 | 5µs | $self->{'localHeaderRelativeOffset'} # spent 5µs making 10 calls to CORE::unpack, avg 540ns/call |
393 | ) = unpack(CENTRAL_DIRECTORY_FILE_HEADER_FORMAT, $header); | ||||
394 | |||||
395 | 10 | 2µs | $self->{'eocdCrc32'} = $self->{'crc32'}; | ||
396 | |||||
397 | 10 | 2µs | if ($fileNameLength) { | ||
398 | 10 | 5µs | 10 | 11µs | $bytesRead = $fh->read($self->{'fileName'}, $fileNameLength); # spent 11µs making 10 calls to IO::Handle::read, avg 1µs/call |
399 | 10 | 1µs | if ($bytesRead != $fileNameLength) { | ||
400 | _ioError("reading central dir filename"); | ||||
401 | } | ||||
402 | } | ||||
403 | 10 | 1µs | if ($extraFieldLength) { | ||
404 | $bytesRead = $fh->read($self->{'cdExtraField'}, $extraFieldLength); | ||||
405 | if ($bytesRead != $extraFieldLength) { | ||||
406 | return _ioError("reading central dir extra field"); | ||||
407 | } | ||||
408 | if ($self->{'archiveZip64'}) { | ||||
409 | my ($status, $zip64) = | ||||
410 | $self->_extractZip64ExtraField($self->{'cdExtraField'}, | ||||
411 | $self->{'uncompressedSize'}, | ||||
412 | $self->{'compressedSize'}, | ||||
413 | $self->{'localHeaderRelativeOffset'}, | ||||
414 | $self->{'diskNumberStart'}); | ||||
415 | return $status if $status != AZ_OK; | ||||
416 | $self->{'zip64'} ||= $zip64; | ||||
417 | } | ||||
418 | } | ||||
419 | 10 | 900ns | if ($fileCommentLength) { | ||
420 | $bytesRead = $fh->read($self->{'fileComment'}, $fileCommentLength); | ||||
421 | if ($bytesRead != $fileCommentLength) { | ||||
422 | return _ioError("reading central dir file comment"); | ||||
423 | } | ||||
424 | } | ||||
425 | |||||
426 | # NK 10/21/04: added to avoid problems with manipulated headers | ||||
427 | 10 | 3µs | if ( $self->{'uncompressedSize'} != $self->{'compressedSize'} | ||
428 | and $self->{'compressionMethod'} == COMPRESSION_STORED) { | ||||
429 | $self->{'uncompressedSize'} = $self->{'compressedSize'}; | ||||
430 | } | ||||
431 | |||||
432 | 10 | 11µs | 20 | 29µs | $self->desiredCompressionMethod($self->compressionMethod()); # spent 24µs making 10 calls to Archive::Zip::Member::desiredCompressionMethod, avg 2µs/call
# spent 5µs making 10 calls to Archive::Zip::Member::compressionMethod, avg 470ns/call |
433 | |||||
434 | 10 | 9µs | return AZ_OK; | ||
435 | } | ||||
436 | |||||
437 | # spent 1.85ms (91µs+1.76) within Archive::Zip::ZipFileMember::rewindData which was called 7 times, avg 264µs/call:
# 7 times (91µs+1.76ms) by Archive::Zip::Member::contents at line 1290 of Archive/Zip/Member.pm, avg 264µs/call | ||||
438 | 7 | 800ns | my $self = shift; | ||
439 | |||||
440 | 7 | 7µs | 7 | 912µs | my $status = $self->SUPER::rewindData(@_); # spent 912µs making 7 calls to Archive::Zip::Member::rewindData, avg 130µs/call |
441 | 7 | 2µs | return $status unless $status == AZ_OK; | ||
442 | |||||
443 | 7 | 6µs | 7 | 425µs | return AZ_IO_ERROR unless $self->fh(); # spent 425µs making 7 calls to Archive::Zip::FileMember::fh, avg 61µs/call |
444 | |||||
445 | 7 | 23µs | 14 | 24µs | $self->fh()->clearerr(); # spent 18µs making 7 calls to Archive::Zip::FileMember::fh, avg 2µs/call
# spent 7µs making 7 calls to IO::Handle::clearerr, avg 957ns/call |
446 | |||||
447 | # Seek to local file header. | ||||
448 | # The only reason that I'm doing this this way is that the extraField | ||||
449 | # length seems to be different between the CD header and the LF header. | ||||
450 | 7 | 6µs | 7 | 193µs | $status = $self->_seekToLocalHeader(); # spent 193µs making 7 calls to Archive::Zip::ZipFileMember::_seekToLocalHeader, avg 28µs/call |
451 | 7 | 1µs | return $status unless $status == AZ_OK; | ||
452 | |||||
453 | # skip local file header | ||||
454 | 7 | 7µs | 7 | 162µs | $status = $self->_skipLocalFileHeader(); # spent 162µs making 7 calls to Archive::Zip::ZipFileMember::_skipLocalFileHeader, avg 23µs/call |
455 | 7 | 1µs | return $status unless $status == AZ_OK; | ||
456 | |||||
457 | # Seek to beginning of file data | ||||
458 | 7 | 10µs | 21 | 42µs | $self->fh()->seek($self->dataOffset(), IO::Seekable::SEEK_SET) # spent 21µs making 7 calls to Archive::Zip::FileMember::fh, avg 3µs/call
# spent 17µs making 7 calls to IO::Seekable::seek, avg 2µs/call
# spent 4µs making 7 calls to Archive::Zip::ZipFileMember::dataOffset, avg 557ns/call |
459 | or return _ioError("seeking to beginning of file data"); | ||||
460 | |||||
461 | 7 | 8µs | return AZ_OK; | ||
462 | } | ||||
463 | |||||
464 | # Return bytes read. Note that first parameter is a ref to a buffer. | ||||
465 | # my $data; | ||||
466 | # my ( $bytesRead, $status) = $self->readRawChunk( \$data, $chunkSize ); | ||||
467 | # spent 591µs (22+569) within Archive::Zip::ZipFileMember::_readRawChunk which was called 7 times, avg 84µs/call:
# 7 times (22µs+569µs) by Archive::Zip::Member::readChunk at line 1118 of Archive/Zip/Member.pm, avg 84µs/call | ||||
468 | 7 | 2µs | my ($self, $dataRef, $chunkSize) = @_; | ||
469 | 7 | 1µs | return (0, AZ_OK) unless $chunkSize; | ||
470 | 7 | 7µs | 14 | 569µs | my $bytesRead = $self->fh()->read($$dataRef, $chunkSize) # spent 558µs making 7 calls to IO::Handle::read, avg 80µs/call
# spent 11µs making 7 calls to Archive::Zip::FileMember::fh, avg 2µs/call |
471 | or return (0, _ioError("reading data")); | ||||
472 | 7 | 7µs | return ($bytesRead, AZ_OK); | ||
473 | } | ||||
474 | |||||
475 | 1 | 2µs | 1; |