File Coverage

blib/lib/Archive/Ipkg.pm
Criterion Covered Total %
statement 185 208 88.9
branch 82 120 68.3
condition 33 48 68.7
subroutine 31 34 91.1
pod 28 28 100.0
total 359 438 81.9


line stmt bran cond sub pod time code
1             package Archive::Ipkg;
2              
3 4     4   153198 use strict;
  4         12  
  4         177  
4 4     4   21 use warnings;
  4         7  
  4         117  
5 4     4   23 use Carp;
  4         10  
  4         496  
6              
7 4     4   4097 use lib qw(.);
  4         3229  
  4         23  
8              
9 4     4   5912 use Archive::Tar;
  4         568295  
  4         375  
10 4     4   49 use Compress::Zlib;
  4         8  
  4         13626  
11              
12             our $VERSION = '0.04';
13              
14             # constructor
15             sub new {
16 3     3 1 54 my $class = shift;
17 3         21 my %opts = @_;
18              
19 3         11 my $self = {};
20              
21 3         11 $self->{sloppy} = 0;
22 3 50       15 $self->{sloppy} = $opts{sloppy}
23             if exists $opts{sloppy};
24              
25 3         9 bless $self, $class;
26              
27             # initialize properties without defaults
28 3 50       13 $self->config_files(@{$opts{config_files}})
  0         0  
29             if exists $opts{config_files};
30 3 50       16 $self->depends($opts{depends})
31             if exists $opts{depends};
32 3 50       15 $self->description($opts{description})
33             if exists $opts{description};
34 3 50       13 $self->filename($opts{filename})
35             if exists $opts{filename};
36 3 50       13 $self->maintainer($opts{maintainer})
37             if exists $opts{maintainer};
38 3 50       10 $self->name($opts{name})
39             if exists $opts{name};
40 3 50       12 $self->preinst_script($opts{preinst_script})
41             if exists $opts{preinst_script};
42 3 50       12 $self->postinst_script($opts{postinst_script})
43             if exists $opts{postinst_script};
44 3 50       10 $self->prerm_script($opts{prerm_script})
45             if exists $opts{prerm_script};
46 3 50       10 $self->postrm_script($opts{postrm_script})
47             if exists $opts{postrm_script};
48              
49             # initialize properties with defaults
50 3 50       24 $self->architecture(exists $opts{architecture} ?
51             $opts{architecture} : $self->default_architecture);
52 3 50       20 $self->priority(exists $opts{priority} ?
53             $opts{priority} : $self->default_priority);
54 3 50       35 $self->section(exists $opts{section} ?
55             $opts{section} : $self->default_section);
56 3 50       26 $self->version(exists $opts{version} ?
57             $opts{version} : $self->default_version);
58              
59             # initialize internal archives
60 3         7 $self->{TAR_CONTROL} = undef; # create when saving
61 3         31 $self->{TAR_DATA} = Archive::Tar->new();
62 3         53 $self->{TAR_IPKG} = undef; # create when saving
63              
64 3         13 return $self;
65             }
66              
67             # control property checking
68             sub sloppy_checks {
69 1     1 1 813 my $self = shift;
70            
71 1         4 $self->{sloppy} = 1;
72             }
73              
74             sub strict_checks {
75 0     0 1 0 my $self = shift;
76              
77 0         0 $self->{sloppy} = 0;
78             }
79              
80              
81             # default values for properties
82             sub default_architecture {
83 4     4 1 20 return "arm";
84             }
85              
86             sub default_priority {
87 4     4 1 20 return "optional";
88             }
89              
90             sub default_section {
91 4     4 1 20 return "misc";
92             }
93              
94             sub default_version {
95 4     4 1 20 return "";
96             }
97              
98             # accessor functions for properties
99             sub config_files {
100 2     2 1 6 my $self = shift;
101 2         3 my $config_files = shift;
102              
103 2 100 66     21 $self->{config_files} = $config_files
104             if (defined $config_files && ref $config_files);
105 2         11 return $self->{config_files};
106             }
107              
108             sub depends {
109 5     5 1 430 my $self = shift;
110 5         10 my $depends = shift;
111            
112 5 100       31 return $self->{depends} unless defined $depends;
113              
114 4 100 100     37 if ($self->{sloppy} || $depends =~ /^[a-z0-9.+-]+(,[a-z0-9.+-]+)*$/) {
115 2         6 $self->{depends} = $depends;
116             } else {
117 2         5 $self->{depends} = undef;
118             }
119            
120 4         20 return $self->{depends};
121             }
122              
123             sub description {
124 6     6 1 13 my $self = shift;
125 6         13 my $description = shift;
126            
127 6 100       84 return $self->{description} unless defined $description;
128              
129 4 100 100     31 if ($self->{sloppy} || $description =~ /\S/) {
130 2         5 $self->{description} = $description;
131             } else {
132 2         4 $self->{description} = undef;
133             }
134            
135 4         16 return $self->{description};
136             }
137              
138             sub filename {
139 2     2 1 4 my $self = shift;
140 2         3 my $filename = shift;
141            
142 2 50       10 if (defined $filename) {
    50          
143 0         0 $self->{filename} = $filename;
144             } elsif (!defined $self->{filename}) {
145 2 100       6 if (defined $self->{name}) {
146 1         3 $self->{filename} = $self->{name};
147              
148 1 50 33     10 $self->{filename} .= "_" . $self->{version}
149             if (defined $self->{version} &&
150             $self->{version} =~ /\S/);
151 1 50 33     10 $self->{filename} .= "_" . $self->{architecture}
152             if (defined $self->{architecture} &&
153             $self->{architecture} =~ /\S/);
154 1         4 $self->{filename} .= ".ipk";
155             }
156             }
157            
158 2         8 return $self->{filename};
159             }
160              
161             sub maintainer {
162 8     8 1 386 my $self = shift;
163 8         14 my $maintainer = shift;
164              
165 8 100       28 return $self->{maintainer} unless defined $maintainer;
166            
167 6 100 100     38 if ($self->{sloppy} || $maintainer =~ /\@/) {
168 3         21 $self->{maintainer} = $maintainer;
169             } else {
170 3         17 $self->{maintainer} = undef;
171             }
172            
173 6         29 return $self->{maintainer};
174             }
175              
176             sub name {
177 11     11 1 19 my $self = shift;
178 11         16 my $name = shift;
179              
180 11 100       33 return $self->{name} unless defined $name;
181              
182 10 100 100     67 if ($self->{sloppy} || $name =~ /^[a-z0-9.+-]+$/) {
183 2         10 $self->{name} = $name;
184             } else {
185 8         17 $self->{name} = undef;
186             }
187              
188 10         41 return $self->{name};
189             }
190              
191             sub preinst_script {
192 2     2 1 595 my $self = shift;
193 2         5 my $preinst_script = shift;
194              
195 2 100       12 $self->{preinst_script} = $preinst_script if defined $preinst_script;
196 2         13 return $self->{preinst_script};
197             }
198              
199             sub postinst_script {
200 2     2 1 6 my $self = shift;
201 2         6 my $postinst_script = shift;
202              
203 2 100       15 $self->{postinst_script} = $postinst_script if defined $postinst_script;
204 2         13 return $self->{postinst_script};
205             }
206              
207             sub prerm_script {
208 2     2 1 6 my $self = shift;
209 2         4 my $prerm_script = shift;
210              
211 2 100       9 $self->{prerm_script} = $prerm_script if defined $prerm_script;
212 2         12 return $self->{prerm_script};
213             }
214              
215             sub postrm_script {
216 2     2 1 7 my $self = shift;
217 2         4 my $postrm_script = shift;
218              
219 2 100       10 $self->{postrm_script} = $postrm_script if defined $postrm_script;
220 2         12 return $self->{postrm_script};
221             }
222              
223             sub architecture {
224 8     8 1 758 my $self = shift;
225 8         15 my $architecture = shift;
226              
227 8 100       26 return $self->{architecture} unless defined $architecture;
228              
229 7 100 100     69 if ($self->{sloppy} || $architecture =~ /^arm|all$/) {
230 6         14 $self->{architecture} = $architecture;
231             } else {
232 1         3 $self->{architecture} = undef;
233             }
234              
235 7         24 return $self->{architecture};
236             }
237              
238             sub priority {
239 11     11 1 1750 my $self = shift;
240 11         20 my $priority = shift;
241              
242 11 100       41 return $self->{priority} unless defined $priority;
243              
244 10 100 100     94 if ($self->{sloppy} || $priority =~ /^required|standard|important|optional|extra$/) {
245 9         29 $self->{priority} = $priority;
246             } else {
247 1         4 $self->{priority} = undef;
248             }
249              
250 10         45 return $self->{priority};
251             }
252              
253             sub section {
254 26     26 1 12537 my $self = shift;
255 26         40 my $section = shift;
256              
257 26         77 my @zaurus_sections = qw(Games Multimedia Communications Settings
258             Utilities Applications Console Misc);
259 26         81 my @familiar_sections = qw(admin base comm editors extras graphics libs
260             misc net text web x11);
261 26         188 my $regex = '^' . join('|', @zaurus_sections, @familiar_sections) . '$';
262              
263 26 100       75 return $self->{section} unless defined $section;
264              
265 25 100 100     608 if ($self->{sloppy} || $section =~ $regex) {
266 24         46 $self->{section} = $section;
267             } else {
268 1         2 $self->{section} = undef;
269             }
270              
271 25         136 return $self->{section};
272             }
273              
274             sub version {
275 7     7 1 13 my $self = shift;
276 7         13 my $version = shift;
277              
278 7 100       22 return $self->{version} unless defined $version;
279              
280 6 100 100     311 if ($self->{sloppy} ||
    100 66        
281             ($version =~ /^[a-zA-Z0-9.+]*$/ && $version =~ /\d/)) {
282 2         5 $self->{version} = $version;
283             } elsif ($version =~ /^\s*$/) {
284 3         17 $self->{version} = "";
285             } else {
286 1         2 $self->{version} = undef;
287             }
288              
289 6         18 return $self->{version};
290             }
291              
292             # verification
293              
294             sub verify {
295 9     9 1 22 my $self = shift;
296 9         15 my $verify = undef;
297            
298             # required: package, version, architecture, maintainer, section, description
299 9 100       35 $verify .= "No package name\n" unless (defined $self->{name});
300             # version should be at least empty
301 9 50       27 $verify .= "No version\n" unless (defined $self->{architecture});
302 9 50       33 $verify .= "No architecture\n" unless (defined $self->{architecture});
303 9 100       30 $verify .= "No maintainer\n" unless (defined $self->{maintainer});
304 9 50       34 $verify .= "No section\n" unless (defined $self->{section});
305              
306 9 100       28 $verify .= "No description\n" unless (defined $self->{description});
307              
308 9         47 return $verify;
309             }
310              
311             # file handling
312              
313             sub add_files {
314 2     2 1 1318 my $self = shift;
315            
316 2         10 return $self->{TAR_DATA}->add_files(@_);
317             }
318              
319             sub add_file {
320 0     0 1 0 my $self = shift;
321 0         0 my ($filename, $new_filename) = @_;
322              
323 0 0       0 $new_filename = $filename unless defined $new_filename;
324 0         0 $new_filename =~ s|^/?|./|;
325            
326 0 0       0 return undef unless open(ADDFILE, "<$filename");
327 0         0 binmode ADDFILE;
328 0         0 local $/; undef $/;
  0         0  
329 0         0 $self->{TAR_DATA}->add_data($new_filename, , { mode => 0100644 });
330 0         0 close(ADDFILE);
331              
332 0         0 return 1;
333             }
334              
335             sub add_file_by_data {
336 1     1 1 889 my $self = shift;
337 1         3 my ($filename, $data, $opts) = @_;
338              
339 1         5 $filename =~ s|^/?|./|;
340              
341 1 0 33     7 $opts = { mode => 0100644 }
      33        
342             unless (defined $opts && ref $opts && exists $opts->{mode});
343              
344 1         5 return $self->{TAR_DATA}->add_data($filename, $data, $opts);
345             }
346              
347             # whole archive handling
348              
349             # returns "control" file contents
350             sub control {
351 1     1 1 41 my $self = shift;
352              
353 1         3 my $control = '';
354              
355 1         4 $control .= "Package: " . $self->{name} . "\n";
356 1 50       7 $control .= "Priority: " . $self->{priority} . "\n"
357             if (defined $self->{priority});
358 1         3 $control .= "Section: " . $self->{section} . "\n";
359 1         3 $control .= "Version: " . $self->{version} . "\n";
360 1         2 $control .= "Architecture: " . $self->{architecture} . "\n";
361 1         4 $control .= "Maintainer: " . $self->{maintainer} . "\n";
362 1 50       4 $control .= "Depends: " . $self->{depends} . "\n"
363             if (defined $self->{depends});
364              
365 1         2 my $desc = $self->{description};
366             # start lines with space
367 1         3 $desc =~ s/\n/ \n/g;
368             # start empty lines with space and .
369 1         2 $desc =~ s/\n \n/\n .\n/g;
370 1         3 $control .= "Description: $desc\n";
371              
372 1         6 return $control;
373             }
374              
375             sub data {
376 2     2 1 532 my $self = shift;
377            
378 2 100       6 return undef if $self->verify;
379             # make control package
380 1         6 $self->{TAR_CONTROL} = Archive::Tar->new();
381              
382 1         23 $self->{TAR_CONTROL}->add_data("./control", $self->control, { mode => 0100644 });
383 1         187 foreach (qw(preinst postinst prerm postrm)) {
384 4 50       11 $self->{TAR_CONTROL}->add_data("./$_", $self->{$_},
385             {mode => 0100755}) if (defined $self->{$_});
386             }
387              
388 1 50 33     5 $self->{TAR_CONTROL}->add_data("./conffiles",
389             join"\n", $self->{config_files}, { mode => 0100644 })
390             if (defined $self->{config_files} && ref $self->{config_files});
391              
392             # make package
393 1         4 $self->{TAR_IPKG} = Archive::Tar->new();
394 1         11 $self->{TAR_IPKG}->add_data("./debian-binary", "2.0\n", { mode => 0100644 });
395              
396 1         170 my ($tar_data);
397              
398 1         7 $tar_data = Compress::Zlib::memGzip($self->{TAR_DATA}->write());
399 1 50       4269 return undef unless defined $tar_data;
400 1         9 $self->{TAR_IPKG}->add_data("./data.tar.gz",
401             $tar_data, { mode => 0100644 });
402              
403 1         238 $tar_data = Compress::Zlib::memGzip($self->{TAR_CONTROL}->write());
404              
405 1 50       832 return undef unless defined $tar_data;
406 1         9 $self->{TAR_IPKG}->add_data("./control.tar.gz",
407             $tar_data, { mode => 0100644 });
408              
409 1         208 $tar_data = Compress::Zlib::memGzip($self->{TAR_IPKG}->write());
410 1         1659 return $tar_data;
411             }
412              
413             sub write {
414 0     0 1   my $self = shift;
415              
416 0           my $filename = $self->filename;
417 0           my $data = $self->data;
418            
419 0 0 0       return undef unless ($filename && defined $data);
420              
421 0 0         open IPKG, ">$filename" or carp "Can't write iPKG '$filename': $!";
422 0           binmode IPKG;
423 0           print IPKG $data;
424 0           close IPKG;
425             }
426              
427             1;
428             __END__