File Coverage

blib/lib/EBook/Ishmael/Unzip.pm
Criterion Covered Total %
statement 33 38 86.8
branch 5 12 41.6
condition 0 12 0.0
subroutine 10 10 100.0
pod 2 2 100.0
total 50 74 67.5


line stmt bran cond sub pod time code
1             package EBook::Ishmael::Unzip;
2 17     17   345 use 5.016;
  17         68  
3             our $VERSION = '2.03';
4 17     17   112 use strict;
  17         32  
  17         474  
5 17     17   73 use warnings;
  17         48  
  17         1036  
6              
7 17     17   95 use Exporter 'import';
  17         30  
  17         1129  
8             our @EXPORT_OK = qw(safe_tmp_unzip unzip);
9              
10 17     17   102 use Cwd;
  17         34  
  17         1652  
11 17     17   111 use File::Spec;
  17         38  
  17         732  
12 17     17   14798 use File::Temp qw(tempdir);
  17         246247  
  17         1607  
13              
14 17     17   12563 use Archive::Zip qw(:ERROR_CODES :CONSTANTS);
  17         1123635  
  17         9415  
15              
16             sub safe_tmp_unzip {
17              
18             # Archive::Zip does not support unzipping to symlinked directory. This is a
19             # problem on platforms like Darwin, as /tmp is symlinked.
20 31 50 0 31 1 1452 if (not -l File::Spec->tmpdir) {
    0 0        
    0 0        
      0        
21 31         273 return tempdir(CLEANUP => 1);
22             # Try working directory...
23             } elsif (! -l cwd and -w cwd) {
24 0         0 return tempdir(DIR => cwd, CLEANUP => 1);
25             # Try HOME...
26             } elsif (
27             exists $ENV{HOME} and
28             -d $ENV{HOME} and
29             ! -l $ENV{HOME} and
30             -w $ENV{HOME}
31             ) {
32 0         0 return tempdir(DIR => $ENV{HOME}, CLEANUP => 1);
33             # Give up and die :-(
34             } else {
35 0         0 die "Could not find a suitable unzip directory\n";
36             }
37              
38             }
39              
40             sub unzip {
41              
42 31     31 1 79 my $zip = shift;
43 31         62 my $out = shift;
44              
45 31         273 my $obj = Archive::Zip->new;
46              
47 31 50       1382 unless ($obj->read($zip) == AZ_OK) {
48 0         0 die "Could not read $zip as a zip archive\n";
49             }
50              
51 31         125608 for my $m ($obj->members) {
52 443 100       19131 $m->unixFileAttributes($m->isDirectory ? 0755 : 0644);
53             }
54              
55 31 50       1725 unless ($obj->extractTree('', $out) == AZ_OK) {
56 0         0 die "Could not unzip $zip to $out\n";
57             }
58              
59 31         950178 return 1;
60              
61             }
62              
63             1;
64              
65             =head1 NAME
66              
67             EBook::Ishmael::Unzip - Unzip Zip archives
68              
69             =head1 SYNOPSIS
70              
71             use EBook::Ishmael::Unzip qw(unzip);
72              
73             unzip($zip, $out);
74              
75             =head1 DESCRIPTION
76              
77             B is a module that provides the C subroutine,
78             which unzips a given Zip file to a specified directory. This is developer
79             documentation, for L user documentation you should consult its manual.
80              
81             =head1 SUBROUTINES
82              
83             =over 4
84              
85             =item $tmpdir = safe_tmp_unzip()
86              
87             Creates and returns a suitable temporary unzip directory. This function exists
88             because Archive::Zip cannot unzip to some kinds of directories, like symlinked
89             ones, which can be problematic on platforms such as Darwin where their F
90             directory is symlinked by default.
91              
92             =item unzip($zip, $out)
93              
94             Unzips C<$zip> to the C<$out> directory. Returns C<1> if successful.
95              
96             =back
97              
98             =head1 AUTHOR
99              
100             Written by Samuel Young, Esamyoung12788@gmail.comE.
101              
102             This project's source can be found on its
103             L. Comments and pull
104             requests are welcome!
105              
106             =head1 COPYRIGHT
107              
108             Copyright (C) 2025-2026 Samuel Young
109              
110             This program is free software: you can redistribute it and/or modify
111             it under the terms of the GNU General Public License as published by
112             the Free Software Foundation, either version 3 of the License, or
113             (at your option) any later version.
114              
115             =cut