File Coverage

blib/lib/Software/Packager/Svr4.pm
Criterion Covered Total %
statement 95 148 64.1
branch 22 58 37.9
condition 11 26 42.3
subroutine 18 23 78.2
pod 12 13 92.3
total 158 268 58.9


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Software::Packager::Svr4 - The Software::Packager extension for System VR4 packages
4              
5             =head1 SYNOPSIS
6              
7             use Software::Packager;
8             my $packager = new Software::Packager('svr4');
9              
10             =head1 DESCRIPTION
11              
12             This module is used to create software packages in a format
13             suitable for installation with pkgadd.
14              
15             =head1 FUNCTIONS
16              
17             =cut
18              
19             package Software::Packager::Svr4;
20              
21 1     1   972 use strict;
  1         2  
  1         40  
22 1     1   1075 use File::Copy;
  1         2740  
  1         74  
23 1     1   8 use File::Path;
  1         2  
  1         51  
24 1     1   6 use File::Basename;
  1         2  
  1         70  
25 1     1   976 use IO::File;
  1         12061  
  1         187  
26 1     1   1044 use POSIX qw(uname);
  1         11085  
  1         7  
27              
28 1     1   1331 use base qw( Software::Packager );
  1         3  
  1         112  
29 1     1   786 use Software::Packager::Object::Svr4;
  1         3  
  1         2369  
30             our $VERSION;
31             $VERSION = substr(q$Revision: 1.2 $, 9);
32              
33             =head2 B
34              
35             This method creates and returns a new Software::Packager::SVR4 object.
36              
37             =cut
38             sub new {
39 1     1 1 14 my $class = shift;
40 1         5 my $self = bless {}, $class;
41              
42 1         16 return $self;
43             }
44              
45             =head2 B
46              
47             $packager->add_item(%object_data);
48              
49             Adds a new object (file, link, etc) to the package.
50              
51             =cut
52              
53             sub add_item {
54 16     16 1 2005 my $self = shift;
55 16         50 my %data = @_;
56 16   50     105 my $object = Software::Packager::Object::Svr4->new(%data) || return;
57              
58             # check that the object has a unique destination
59             return
60 16 100       125 if exists $self->{OBJECTS}->{$object->destination};
61              
62 1         15 $self->{OBJECTS}->{$object->destination} = $object;
63             }
64              
65             sub get_all_classes {
66 1     1 0 3 my $self = shift;
67 1         2 my %class;
68              
69 1         18 foreach($self->get_directory_objects, $self->get_file_objects,
70             $self->get_link_objects) {
71 0         0 $class{$_->class}++;
72             }
73 1         192 return keys %class;
74             }
75              
76             =head2 B
77              
78             $packager->package();
79              
80             Create the package.
81              
82             =cut
83              
84             sub package {
85 1     1 1 2 my $self = shift;
86 1         10 my $dir = $self->output_dir;
87              
88 1   50     30 my $pkginfo = IO::File->new(">$dir/pkginfo")
89             || die "Couldn't open pkginfo for output: $!\n";
90 1         279 my %info = $self->info;
91             print $pkginfo "$_=$info{$_}\n"
92 1         40 for keys %info;
93              
94 1   50     9 my $pkgmap = IO::File->new(">$dir/pkgmap")
95             || die "Couldn't open pkgmap for output: $!\n";
96              
97 1         147 mkdir "$dir/reloc", 0755;
98 1         28 chdir "$dir/reloc";
99 1         2 my $maxlength = 0;
100 1         11 foreach($self->get_directory_objects, $self->get_file_objects,
101             $self->get_link_objects) {
102 0         0 warn $_->destination, ", ", $_->prototype, "\n";
103 0 0       0 if($_->prototype eq 'f') {
    0          
104 0 0       0 open(IN, $_->source)
105             || die "Couldn't open ", $_->source, " for input: $!\n";
106 0 0       0 open(OUT, ">./".$_->destination)
107             || die "Couldn't open ", $_->destination, " for output: $!\n";
108 0         0 ($_->{length},$_->{crc}) = _sum_copy(\*IN, \*OUT);
109 0 0       0 $maxlength = $_->{length} if $_->{length} > $maxlength;
110 0         0 $_->{mtime} = [lstat($_->source)]->[10];
111 0         0 close IN;
112 0         0 close OUT;
113 0         0 chmod $_->mode, $_->destination;
114             } elsif($_->prototype eq 'd') {
115 0         0 mkdir $_->destination, $_->mode;
116             }
117              
118 0         0 $pkgmap->print(_pkgmap_line($_));
119             }
120 1         108 chdir "../..";
121              
122 1         18 print $pkgmap ":1 ". int($maxlength / 512). "\n";
123 1         45 $pkgmap->close;
124             }
125              
126             # an implementation of the 'cksum' utility in perl. written for the perl
127             # power tools (ppt) project by theo van dinter (felicity@kluge.net).
128             #
129             # id: cksum,v 1.3 1999/03/04 17:14:08 felicity exp
130             # modified to copy the file while it sums
131             sub _sum_copy {
132 0     0   0 my($fh) = shift;
133 0         0 my($ofh) = shift;
134 0         0 my($crc) = my($len) = 0;
135 0         0 my($buf,$num,$i);
136 0         0 my($buflen) = 4096; # buffer is "4k", you can up it if you want...
137              
138 0         0 while($num = sysread $fh, $buf, $buflen) {
139 0         0 $len += $num;
140 0         0 $crc += unpack("%32C*", $buf);
141 0         0 syswrite $ofh, $buf;
142             }
143              
144             # crc = s (total of bytes)
145 0         0 $crc = ($crc & 0xffff) + ($crc & 0xffffffff) / 0x10000; # r
146 0         0 $crc = ($crc & 0xffff) + ($crc / 0x10000); # cksum
147              
148 0         0 return $len,int($crc),($len+511)/512; # round # of blocks up ...
149             }
150              
151             sub _pkgmap_line {
152 0     0   0 my $finfo = shift;
153              
154 0 0       0 (defined $finfo->part ? $finfo->part : "1") . " " .
    0          
    0          
155             $finfo->prototype . " " .
156             (defined $finfo->class ? $finfo->class : "none") . " " .
157              
158             $finfo->destination . " " . sprintf("%04o",$finfo->mode)
159             . " " . $finfo->user . " " . $finfo->group . " " .
160             ($finfo->prototype eq 'f' ? $finfo->{length} .
161             " " . $finfo->{crc} . " "
162             . $finfo->{mtime} . "\n" : "\n")
163             }
164              
165             =head2 B
166              
167             This method returns a hash that is filled with the necessary
168             information for a pkginfo file that conforms to the SYSV format.
169              
170             =cut
171              
172             sub info {
173 1     1 1 2 my $self = shift;
174 1         2 my %info;
175              
176 1   33     7 $info{PKG} = $self->package_name || warn "No package name.\n";
177 1   33     5 $info{NAME} = $self->program_name || warn "No program name.\n";
178 1   33     7 $info{VERSION} = $self->version || warn "No version number.\n";
179 1 50       4 $info{ARCH} = $self->architecture
180             if $self->architecture;
181 1   33     6 $info{PSTAMP} = $self->creator
182             || POSIX::strftime([POSIX::uname]->[1].'%Y%m%d%H%M%S', localtime);
183 1         11 $info{CLASSES} = join(", ",$self->get_all_classes);
184 1 50       4 $info{CATEGORY} = $self->category
185             if $self->category;
186 1 50       19 $info{VENDOR} = $self->vendor
187             if $self->vendor;
188 1         21 $info{BASEDIR} = $self->install_dir;
189 1 50       5 $info{EMAIL} = $self->email_contact
190             if $self->email_contact;
191              
192 1         53 return %info;
193             }
194              
195              
196             =head2 B
197              
198             Define the package name.
199              
200             =cut
201              
202             sub package_name {
203 7     7 1 477 my $self = shift;
204 7         11 my $name = shift;
205              
206 7 100       43 return $self->{PACKAGE_NAME}
207             unless $name;
208              
209 1         4 for ($name) {
210 1 50       8 if (m{^(?![a-zA-Z])}) {
211 1         33 warn qq{Warning: Package name "$name" does not start with a letter.
212             Removing non letters from the start.\n};
213 1         8 s{^(.*?)(?=[a-zA-Z])(.*)}{$2};
214             }
215 1 50       5 if (/[^a-zA-Z0-9+-]!/) {
216 0         0 warn qq{Warning: Package name "$name" contains
217             charaters other that alphanumeric, + and -. Removing them.\n};
218 0         0 tr/a-zA-Z0-9+-//cd;
219             }
220 1 50       4 if (length > 256) {
221 0         0 warn qq{Warning: Package name "$name" is longer than 9 charaters.
222             Truncating to 9 charaters.\n};
223 0         0 $_ = substr($_, 0, 256);
224             }
225 1 50       6 if (/^install$|^new$|^all$/) {
226 0         0 warn "Warning: The package name $name is reserved.\n";
227             }
228 1         23 $self->{PACKAGE_NAME} = $_;
229             }
230              
231             }
232              
233             =head2 B
234              
235             This is used to specify the full package name.
236              
237             The program name must be less that 256 charaters.
238              
239             For more details see the pkginfo(4) man page.
240              
241             =cut
242              
243             sub program_name {
244 3     3 1 31 my $self = shift;
245 3         5 my $name = shift;
246              
247 3 50 33     21 return ($self->{PROGRAM_NAME} || $self->package_name)
248             unless $self->{PROGRAM_NAME};
249 0         0 for($name) {
250 0 0       0 if (length > 256) {
251 0         0 warn qq{Warning: Package name "$_" is longer than 256 charaters.
252             Truncating to 256 charaters.\n};
253 0         0 $_ = substr($_, 0, 256);
254             }
255 0         0 $self->{PROGRAM_NAME} = $_;
256             }
257              
258             }
259              
260             =head2 B
261              
262             The architecture must be a comma seperated list of alphanumeric tokens that
263             indicate the architecture associated with the package.
264              
265             The maximum length of a token is 16 charaters.
266              
267             A token should be in the format "instruction set"."platform group"
268             where:
269              
270             =over
271              
272             =item instruction set is in the format of `uname -p`
273              
274             =item platform group is in the format of `uname -m`
275              
276             =back
277              
278             If the architecture is not set then the current instruction set is used.
279              
280             For more details see the pkginfo(4) man page.
281              
282             =cut
283              
284             sub architecture {
285 5     5 1 11762 my $self = shift;
286 5         35 my $name = shift;
287              
288 5 100       35 $self->{ARCHITECTURE} = $name
289             if $name;
290 5   66     95 $self->{ARCHITECTURE} ||= [uname]->[4];
291             }
292              
293             =head2 B
294              
295             This method is used to check the format of the version and return it in the
296             format required for SVR4.
297              
298             =item *
299              
300             The version must be 256 charaters or less.
301              
302             =item *
303              
304             The first charater cannot be a left parenthesis.
305              
306             The recommended format is an arbitrary string of numbers in Dewey-decimal
307             format.
308             For more datails see the pkginfo(4) man page.
309              
310             =cut
311             sub version {
312 4     4 1 58 my $self = shift;
313 4         9 my $version = shift;
314              
315 4 100       11 if ($version) {
316 2 50       8 if (substr($version, 0, 1) eq '(') {
317 0         0 warn "Warning: The version starts with a left parenthesis.
318             Removing it.\n";
319 0         0 $version = substr($version,1);
320             }
321 2 50       10 if (length $version > 256) {
322 0         0 warn "Warning: The version is longer than 256 charaters.
323             Truncating it.\n";
324 0         0 $version = substr($version,0,256);
325             }
326 2         12 $self->{PACKAGE_VERSION} = $version;
327             }
328              
329 4         16 return $self->{PACKAGE_VERSION};
330             }
331              
332             =head2 B
333              
334             $packager->install_dir('/usr/local');
335             my $base_dir = $packager->install_dir;
336              
337             This method sets the base directory for the software to be installed.
338             The installation directory must start with a "/".
339              
340             =cut
341              
342             sub install_dir {
343 3     3 1 1822 my $self = shift;
344 3         8 my $value = shift;
345              
346 3 100 50     29 return ($self->{BASEDIR} || '/')
347             unless $value;
348 1         7 for($value) {
349 1 50       15 if (substr($_,0,1) ne '/') {
350 1         117 warn qq{Warning: The installation directory does not start with a "/".
351             Prepending "/" to $value.};
352 1         13 $_ = "/$value";
353             }
354 1         16 $self->{BASEDIR} = $_;
355             }
356             }
357              
358             =head2 B
359              
360             $packager->compatible_version('/some/path/file');
361              
362             or
363              
364             $packager->compatible_version($compver_stored_in_string);
365              
366             my $compatible_version = $packager->compatible_version();
367              
368             This method sets the compatible versions file for the software to
369             be installed.
370              
371             =cut
372              
373             sub compatible_version {
374 0     0 1   my $self = shift;
375 0           my $value = shift;
376              
377 0 0         $self->{COMPVER} = $value
378             if $value;
379 0           return $self->{COMPVER};
380             }
381              
382             =head2 B
383              
384             $packager->space('/some/path/file');
385              
386             or
387              
388             $packager->space($space_data_stored_in_string);
389             my $space = $packager->space();
390              
391             This method sets the space file for the software to be installed.
392              
393             =cut
394              
395             sub space {
396 0     0 1   my $self = shift;
397 0           my $value = shift;
398              
399 0 0         $self->{SPACE} = $value
400             if $value;
401 0           return $self->{SPACE};
402             }
403              
404             =head2 B
405              
406             $packager->request_script('/some/path/file');
407              
408             or
409              
410             $packager->request_script($request_script_stored_in_string);
411             my $request_script = $packager->request_script();
412              
413             This method sets the space file for the software to be installed.
414              
415             =cut
416              
417             sub request_script {
418 0     0 1   my $self = shift;
419 0           my $value = shift;
420              
421 0 0         $self->{REQUEST_SCRIPT} = $value
422             if $value;
423 0           return $self->{REQUEST_SCRIPT};
424             }
425              
426             1;
427             __END__