Archive-Zip
view release on metacpan or search on metacpan
lib/Archive/Zip/Archive.pm view on Meta::CPAN
}
foreach my $member ($self->members()) {
# (Re-)set object member zip64 flag. Here is what
# happens next to that flag:
#
# $member->_writeToFileHandle
# Determines a local flag value depending on
# necessity and user desire and ors it to
# the object member
# $member->_writeLocalFileHeader
# Queries the object member to write appropriate
# local header
# $member->_writeDataDescriptor
# Queries the object member to write appropriate
# data descriptor
# $member->_writeCentralDirectoryFileHeader
# Determines a local flag value depending on
# necessity and user desire. Writes a central
# directory header appropriate to the local flag.
# Ors the local flag to the object member.
$member->{'zip64'} = 0;
my ($status, $memberSize) =
$member->_writeToFileHandle($fh, $fhIsSeekable, $offset,
$self->desiredZip64Mode());
$member->endRead();
return $status if $status != AZ_OK;
$offset += $memberSize;
# Change this so it reflects write status and last
# successful position
$member->{'wasWritten'} = 1;
$self->{'writeCentralDirectoryOffset'} = $offset;
}
return $self->writeCentralDirectory($fh);
}
# Write zip back to the original file,
# as safely as possible.
# Returns AZ_OK if successful.
sub overwrite {
my $self = shift;
return $self->overwriteAs($self->{'fileName'});
}
# Write zip to the specified file,
# as safely as possible.
# Returns AZ_OK if successful.
sub overwriteAs {
my $self = shift;
my $zipName = (ref($_[0]) eq 'HASH') ? $_[0]->{filename} : shift;
return _error("no filename in overwriteAs()") unless defined($zipName);
my ($fh, $tempName) = Archive::Zip::tempFile();
return _error("Can't open temp file", $!) unless $fh;
(my $backupName = $zipName) =~ s{(\.[^.]*)?$}{.zbk};
my $status = $self->writeToFileHandle($fh);
$fh->close();
$fh = undef;
if ($status != AZ_OK) {
unlink($tempName);
_printError("Can't write to $tempName");
return $status;
}
my $err;
# rename the zip
if (-f $zipName && !rename($zipName, $backupName)) {
$err = $!;
unlink($tempName);
return _error("Can't rename $zipName as $backupName", $err);
}
# move the temp to the original name (possibly copying)
unless (File::Copy::move($tempName, $zipName)
|| File::Copy::copy($tempName, $zipName)) {
$err = $!;
rename($backupName, $zipName);
unlink($tempName);
return _error("Can't move $tempName to $zipName", $err);
}
# unlink the backup
if (-f $backupName && !unlink($backupName)) {
$err = $!;
return _error("Can't unlink $backupName", $err);
}
return AZ_OK;
}
# Used only during writing
sub _writeCentralDirectoryOffset {
shift->{'writeCentralDirectoryOffset'};
}
sub _writeEOCDOffset {
shift->{'writeEOCDOffset'};
}
# Expects to have _writeEOCDOffset() set
sub _writeEndOfCentralDirectory {
my ($self, $fh, $membersZip64) = @_;
my $zip64 = 0;
my $versionMadeBy = $self->versionMadeBy();
my $versionNeededToExtract = $self->versionNeededToExtract();
my $diskNumber = 0;
my $diskNumberWithStartOfCentralDirectory = 0;
my $numberOfCentralDirectoriesOnThisDisk = $self->numberOfMembers();
my $numberOfCentralDirectories = $self->numberOfMembers();
my $centralDirectorySize =
$self->_writeEOCDOffset() - $self->_writeCentralDirectoryOffset();
my $centralDirectoryOffsetWRTStartingDiskNumber =
$self->_writeCentralDirectoryOffset();
my $zipfileCommentLength = length($self->zipfileComment());
my $eocdDataZip64 = 0;
$eocdDataZip64 ||= $numberOfCentralDirectoriesOnThisDisk > 0xffff;
$eocdDataZip64 ||= $numberOfCentralDirectories > 0xffff;
$eocdDataZip64 ||= $centralDirectorySize > 0xffffffff;
$eocdDataZip64 ||= $centralDirectoryOffsetWRTStartingDiskNumber > 0xffffffff;
if ( $membersZip64
|| $eocdDataZip64
|| $self->desiredZip64Mode() == ZIP64_EOCD) {
return _zip64NotSupported() unless ZIP64_SUPPORTED;
$zip64 = 1;
$versionMadeBy = 45 if ($versionMadeBy == 0);
$versionNeededToExtract = 45 if ($versionNeededToExtract < 45);
$self->_print($fh, ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIGNATURE_STRING)
or return _ioError('writing zip64 EOCD record signature');
my $record = pack(
ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_FORMAT,
ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_LENGTH +
SIGNATURE_LENGTH - 12,
$versionMadeBy,
$versionNeededToExtract,
$diskNumber,
$diskNumberWithStartOfCentralDirectory,
$numberOfCentralDirectoriesOnThisDisk,
$numberOfCentralDirectories,
$centralDirectorySize,
( run in 1.134 second using v1.01-cache-2.11-cpan-39bf76dae61 )