From 7f77cd7fbc9ea2b4c1abd640e00d7f8bb142a4ef Mon Sep 17 00:00:00 2001 From: "David E. Wheeler" Date: Thu, 14 Mar 2024 18:31:46 -0400 Subject: [PATCH] Fix handling of symlinks extracted from zip files Setting unix attributes was breaking the detection of symlinks by Archive::Zip, so it was just writing out a file with the name of the linked file in it. Fix it by instead removing an existing file if it exists and not setting permissions for symlinks. This allows Arhive::Zip to always create a proper symlink. While at it, change the permissions for files to we writable by the owner, so as to avoid any other permissions issues when re-indexing an archive, which needs to replace existing files. Finallky, don't abandon unzipping a file on error, but just move on to the next file. --- Changes | 2 ++ lib/PGXN/API/Sync.pm | 16 +++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Changes b/Changes index 8ec0676..c8fd713 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,8 @@ Revision history for Perl extension PGXN::API 0.20.2 + - Fixed symlinks extracted from Zip files and permission errors when + re-indexing distributions. 0.20.1 2024-02-15T22:18:14Z - Fixed a bug where a testing extension's version and abstract was not diff --git a/lib/PGXN/API/Sync.pm b/lib/PGXN/API/Sync.pm index 9965e89..18b438b 100644 --- a/lib/PGXN/API/Sync.pm +++ b/lib/PGXN/API/Sync.pm @@ -194,14 +194,20 @@ sub unzip { make_path $dist_dir unless -e $dist_dir && -d _; foreach my $member ($zip->members) { - # Make sure the file is readable by everyone - $member->unixFileAttributes( $member->isDirectory ? 0755 : 0444 ); my $fn = catfile $dist_dir, split m{/} => $member->fileName; say " $fn\n" if $self->verbose > 2; + + if ($member->isSymbolicLink) { + # Delete exsting so Archive::Zip won't fail to create it. + warn "Cannot unlink $fn: $!\n" if -e $fn && !unlink $fn; + } else { + # Make sure the member is readable by everyone. + $member->unixFileAttributes( $member->isDirectory ? 0755 : 0644 ); + } + if ($member->extractToFileNamed($fn) != AZ_OK) { - warn "Error extracting $zip_path\n"; - ## XXX clean up the mess here. - return; + warn "Error extracting $fn from $zip_path\n"; + next; } }