File Coverage

blib/lib/FreeBSD/Pkgs.pm
Criterion Covered Total %
statement 9 284 3.1
branch 0 140 0.0
condition n/a
subroutine 3 7 42.8
pod 4 4 100.0
total 16 435 3.6


line stmt bran cond sub pod time code
1             package FreeBSD::Pkgs;
2              
3 1     1   36287 use warnings;
  1         2  
  1         36  
4 1     1   6 use strict;
  1         1  
  1         38  
5 1     1   5 use base 'Error::Helper';
  1         6  
  1         1045  
6              
7             =head1 NAME
8              
9             FreeBSD::Pkgs - Reads the FreeBSD installed packaged DB.
10              
11             =head1 VERSION
12              
13             Version 0.2.0
14              
15             =cut
16              
17             our $VERSION = '0.2.0';
18              
19              
20             =head1 SYNOPSIS
21              
22             The following example prints out the package information.
23              
24              
25             use FreeBSD::Pkgs;
26            
27             $pkgdb=FreeBSD::Pkgs->new;
28            
29             $pkgdb->parseInstalled;
30            
31             while(my ($name, $pkg) = each %{$pkgdb->{packages}}){
32             print $name."\nComment=".$pkg->{comment}."\n";
33            
34             #prints the packages that require it
35             if (defined($pkg->{requiredby})){
36             my $requiredbyInt=0;
37             while (defined($pkg->{requiredby}[$requiredbyInt])){
38             print $name." required by ".$pkg->{requiredby}[$requiredbyInt]."\n";
39             $requiredbyInt++;
40             }
41             }
42            
43             #if the extract-in-place option is set, print it
44             if (defined($pkg->{contents}{extract-in-place})){
45             print $name." is set to extract in place\n";
46             }
47            
48             #if the extract-in-place option is set, print it
49             if (defined($pkg->{contents}{preserve})){
50             print $name." is set to preserve the old file\n";
51             }
52            
53             #print the mtree
54             if (defined($pkg->{contents}{mtree})){
55             print $name." the mtree for this package is '".$pkg->{contents}{mtree}."'\n";
56             }
57            
58             #print installed files and associated info
59             if (defined($pkg->{contents}{files})){
60             my @files=keys(%{$pkg->{contents}{files}});
61             my $filesInt=0;
62             while (defined($files[$filesInt])){
63             print $name." installs ".$files[$filesInt]." md5='".
64             $pkg->{contents}{files}{$files[$filesInt]}{MD5}."' ";
65             #prints the the group if there is a specific one for the file
66             if (defined($pkg->{contents}{files}{$files[$filesInt]}{group})) {
67             print " group='".$pkg->{contents}{files}{$files[$filesInt]}{group}."'";
68             }
69             #prints the the user if there is a specific one for the file
70             if (defined($pkg->{contents}{files}{$files[$filesInt]}{user})) {
71             print " user='".$pkg->{contents}{files}{$files[$filesInt]}{user}."'";
72             }
73             #prints the the mode if there is a specific one for the file
74             if (defined($pkg->{contents}{files}{$mfiles[$filesInt]}{mode})) {
75             print " mode='".$pkg->{contents}{files}{$files[$filesInt]}{mode}."'";
76             }
77             #prints the directory if it is not relative to the base
78             if (defined($pkg->{contents}{files}{$mfiles[$filesInt]}{cwd})) {
79             print " cwd='".$pkg->{contents}{files}{$files[$filesInt]}{cwd}."'";
80             }
81             #print if the file is set to be ignored
82             if (defined($pkg->{contents}{files}{$mfiles[$filesInt]}{ignore})) {
83             print " ignore='".$pkg->{contents}{files}{$files[$filesInt]}{ignore}."'";
84             }
85             #print if the file is set to be ignored
86             if (defined($pkg->{contents}{files}{$mfiles[$filesInt]}{ignore_inst})) {
87             print " ignore_inst='".$pkg->{contents}{files}{$files[$filesInt]}{ignore_inst}."'";
88             }
89             print "\n";
90             $filesInt++;
91             }
92             }
93            
94             #prints the conflict information
95             my $conflictInt=0;
96             while (defined($pkg->{contents}{conflict}[$conflictInt])){
97             print $name." conflicts with ".$pkg->{contents}{conflict}[$conflictInt]."\n";
98             $conflictInt++;
99             }
100            
101             #print dirrm stuff
102             my $dirrmInt=0;
103             while (defined($pkg->{contents}{dirrm}[$dirrmInt])){
104             print $name." conflicts with ".$pkg->{contents}{dirrm}[$dirrmInt]."\n";
105             $dirrmInt++;
106             }
107            
108             print "\n";
109             }
110              
111             =head1 FUNCTIONS
112              
113             =head2 new
114              
115             #creates a new object with the default settings
116             my $pkgdb=FreeBSD::Pkgs->new;
117              
118             #creates a new package with the a specified pkgdb dir
119             my $pkgdb=FreeBSD::Pkgs->new({pkgdb=>'/var/db/pkg'});
120              
121             #if this is true there is a error
122             if($pkgdb->error){
123             warn('Error:'.$pkgdb->error.': '.$pkgdb->errorString);
124             }
125              
126             =head3 arguement keys
127              
128             =over
129              
130             =item pkgdb
131              
132             If this key is defined, it uses this dir to use for the package db.
133              
134             The same environmental variables as used by the package tools are respected.
135              
136             =back
137              
138             =cut
139              
140             sub new{
141 0     0 1   my %args;
142 0 0         if (defined($_[1])) {
143 0           %args=%{$_[1]};
  0            
144             }
145              
146             #blesses it and inits the hash
147 0           my $self={
148             packages=>{},
149             error=>undef,
150             errorString=>'',
151             };
152 0           bless $self;
153              
154             #figures out what to use for pkgdb
155 0 0         if (!defined($args{pkgdb})){
156 0 0         if (!defined($ENV{PKG_DBDIR})) {
157 0           $self->{pkgdb}='/var/db/pkg/';
158             }else{
159 0           $self->{pkgdb}=$ENV{PKG_DBDIR};
160             }
161             }else{
162 0           $self->{pkgdb}=$args{pkgdb};
163             }
164              
165             # #makes sure it exists
166             # if (! -e $args{pkgdb}){
167             # warn("FreeBSD-Pkgs:1: PKG_DBDIR, '".$args{pkgdb}."' does not exist");
168             # $self->{error}='1';
169             # return $self;
170             # }
171              
172             # #reads the packages
173             # if (opendir(PKGDBDIR, $args{pkgdb})){
174             # warn("FreeBSD-Pkgs:2: Could not open PKG_DBDIR, '".$args{pkgdb}."',");
175             # exit 2;
176             # }
177             # my @packages=readdir(PKGDBDIR);
178             # closedir(PKGDBDIR);
179              
180             # #removes directories that start with '.'
181             # @packages=grep(/^\./, @packages);
182              
183             # #processes them all
184             # my @packagesInt=0;
185             # while (defined($packages[$packagesInt])){
186             # #only process it if it is a directory
187             # if (-d $args{pkgdb}.'/'.$packages[$packagesInt]){
188             # my %returned=$self->paseInstalledPkg($packages[$packagesInt]);
189             # #only add it if it is not an error
190             # if (!defined($self->{error})) {
191             # $self->{packages}{$packages[$packagesInt]}=%returned;
192             # }else{
193             # warn('FreeBSD-Pkgs:3: Parsing "'.$packages[$packagesInt].'" as failed.');
194             # }
195             # }else{
196             # #non-fatal
197             # warn('FreeBSD-Pkgs:3: Skipping "'.$packages[$packagesInt].'" as it is not a directory');
198             # }
199             # }
200              
201 0           return $self;
202             }
203              
204             =head2 parseContents
205              
206             This parses the '+CONTENTS' file for a package. The only required is a
207             string containing the contents of the file to be parsed.
208              
209             =head3 args hash
210              
211             =head4 files
212              
213             A boolean controlling if file information is parsed or not.
214              
215             my %contents=$pkgdb->parseContents($contentString, %args);
216             if($pkgdb->error){
217             warn('Error:'.$pkgdb->error.': '.$pkgdb->errorString);
218             }
219              
220             =cut
221              
222             sub parseContents{
223 0     0 1   my $self=$_[0];
224 0           my $contents=$_[1];
225 0           my %args;
226 0 0         if (defined($_[2])) {
227 0           %args=%{$_[2]};
  0            
228             }
229              
230 0 0         if ( ! $self->errorblank ){
231 0           return undef;
232             }
233              
234             #process the file info unless told to do otherwise
235 0 0         if (!defined($args{file})) {
236 0           $args{file}=1;
237             }
238              
239             #splits the contents at every new line
240 0           my @contentsA=split(/\n/, $contents);
241              
242 0           my %hash;
243              
244 0           my $contentsAint=0;
245              
246             #holds the the last line matching /^\@pkgdep/
247 0           my $pkgdep=undef;
248              
249             #holds the last file
250 0           my $file=undef;
251            
252             #defined if a file has a specific mode
253 0           my $mode=undef;
254              
255             #defined if a file has a specific group
256 0           my $group=undef;
257              
258             #defined if a file has a specific user
259 0           my $user=undef;
260              
261             #holds any second cwds that pop up
262 0           my $cwd=undef;
263              
264             #if this is set to true, the ignore flag is set on a file
265 0           my $ignore=undef;
266              
267             #if this is set to true, the ignore_inst flag is set on a file
268 0           my $ignore_inst=undef;
269              
270             #process it
271 0           while (defined($contentsA[$contentsAint])){
272 0           my $line=$contentsA[$contentsAint];
273 0           chomp($line);
274              
275             #set to true if matched... used for checking at the end of this loop
276 0           my $matched=undef;
277              
278             #handles it if the PKG_FORMAT_REVISION
279 0 0         if ($line =~ /^\@comment PKG_FORMAT_REVISION:/){
280 0           $line =~ s/^\@comment PKG_FORMAT_REVISION://;
281 0           $hash{PKG_FORMAT_REVISION}=$line;
282              
283 0           goto contentsParseLoopEnd;
284             }
285              
286             #handles it if it is the name line
287 0 0         if ($line =~ /^\@name / ){
288 0           $line =~ s/^\@name //;
289 0           $hash{name}=$line;
290              
291 0           goto contentsParseLoopEnd;
292             }
293            
294             #handles ignore lines
295 0 0         if ($args{file}) {
296 0 0         if ($line =~ /^\@ignore/ ){
297 0           $line =~ s/^\@ignore//;
298 0           $ignore=1;
299            
300 0           goto contentsParseLoopEnd;
301             }
302             }else {
303 0           goto contentsParseLoopEnd;
304             }
305              
306             #handles ignore lines
307 0 0         if ($line =~ /^\@srcdir / ){
308 0           $line =~ s/^\@srcdir //;
309 0           $hash{srcdir}=$line;
310              
311 0           goto contentsParseLoopEnd;
312             }
313              
314             #handles ignore_inst lines
315 0 0         if ($line =~ /^\@ignore_inst/ ){
316 0           $line =~ s/^\@ignore_inst//;
317 0           $ignore_inst=1;
318              
319 0           goto contentsParseLoopEnd;
320             }
321              
322             #handles it if origin line
323 0 0         if ($line =~ /^\@comment ORIGIN:/){
324 0           $line =~ s/^\@comment ORIGIN://;
325 0           $hash{origin}=$line;
326              
327 0           goto contentsParseLoopEnd;
328             }
329              
330             #extract-in-place options
331 0 0         if ($line =~ /^\@option extract-in-place/){
332 0           $line =~ s/^\@option extract-in-place//;
333 0           $hash{'extract-in-place'}=1;
334              
335 0           goto contentsParseLoopEnd;
336             }
337              
338             #extract-in-place option
339 0 0         if ($line =~ /^\@option preserve/){
340 0           $line =~ s/^\@option preserve//;
341 0           $hash{preserve}=1;
342              
343 0           goto contentsParseLoopEnd;
344             }
345              
346             #handles it if base dir line
347 0 0         if ($line =~ /^\@cwd /){
348 0           $line =~ s/^\@cwd //;
349 0 0         if (!defined($hash{cwd})){
350 0           $hash{cwd}=$line;
351             }else {
352 0 0         if ($hash{cwd} eq $line){
353 0           $cwd=undef;
354             }else{
355 0           $cwd=$line;
356             }
357             }
358              
359 0           goto contentsParseLoopEnd;
360             }
361              
362 0 0         if ($args{file}){
363             #handles it group lines
364 0 0         if ($line =~ /^\@group/){
365 0           $line =~ s/^\@group//;
366            
367             #remove any spaces at the beginning
368 0           $line =~ s/^\ *//;
369            
370 0 0         if ($line eq "") {
371 0           $group=undef;
372             }else{
373 0           $group=$line;
374             }
375            
376 0           goto contentsParseLoopEnd;
377             }
378              
379             #handles it mode lines
380 0 0         if ($line =~ /^\@mode/){
381 0           $line =~ s/^\@mode//;
382            
383             #remove any spaces at the beginning
384 0           $line =~ s/^\ *//;
385            
386 0 0         if ($line eq "") {
387 0           $mode=undef;
388             }else{
389 0           $mode=$line;
390             }
391            
392 0           goto contentsParseLoopEnd;
393             }
394             }
395             #handles it if metree line
396 0 0         if ($line =~ /^\@mtree /){
397 0           $line =~ s/^\@mtree //;
398             #it should only be defined once
399 0 0         if (!defined($hash{mtree})){
400 0           $hash{mtree}=$line;
401             }
402              
403 0           goto contentsParseLoopEnd;
404             }
405              
406             #handles it if dependency line
407 0 0         if ($line =~ /^\@pkgdep /){
408 0           $line =~ s/^\@pkgdep //;
409              
410 0           $pkgdep=$line;
411              
412             #creates the dep hash if it already exists
413 0 0         if (!defined($hash{deps})) {
414 0           $hash{deps}={};
415             }
416              
417             #sets up the depdency hash
418 0           $hash{deps}{$line}={};
419              
420 0           goto contentsParseLoopEnd;
421             }
422              
423             #handles it if line describing the origin of a dependency
424 0 0         if ($line =~ /^\@comment DEPORIGIN:/){
425 0 0         if (!defined($pkgdep)){
426 0 0         if (defined($hash{name})){
427 0           $self->warnString('A line matching /^\@comment DEPORIGIN:/'.
428             ' was found, but no previous package dependencies were found. Line="'.
429             $line.'" name="'.$hash{name}.'"');
430             }else {
431 0           $self->warnString('A line matching /^\@comment DEPORIGIN:/'.
432             ' was found, but no previous package dependencies were found. Line="'.
433             $line.'"');
434             }
435             }
436              
437 0           $line =~ s/^\@comment DEPORIGIN://;
438              
439 0           $hash{deps}{$pkgdep}{origin}=$line;
440              
441 0           goto contentsParseLoopEnd;
442             }
443              
444             #handles it if it is a file
445 0 0         if ($args{file}) {
446 0 0         if ($line !~ /^\@/){
447 0 0         if (!defined($hash{files})){
448 0           $hash{files}={};
449             }
450            
451 0           $file=$line;
452            
453 0           $hash{files}{$line}={};
454            
455             #if a specific group is set, set it for the group
456 0 0         if (defined($group)){
457 0           $hash{files}{$line}{group}=$group;
458             }
459              
460             #if a specific user is set, set it for the group
461 0 0         if (defined($user)){
462 0           $hash{files}{$line}{user}=$user;
463             }
464              
465             #if a specific mode is set, set it for the file
466 0 0         if (defined($mode)){
467 0           $hash{files}{$line}{mode}=$mode;
468             }
469            
470             #sets the ignore flag on a file if it is defined
471 0 0         if ($ignore){
472 0           $hash{files}{$line}{ignore}=1;
473 0           $ignore=undef;
474             }
475              
476             #sets the ignore_inst flag on a file if it is defined
477 0 0         if ($ignore){
478 0           $hash{files}{$line}{ignore_inst}=1;
479 0           $ignore_inst=undef;
480             }
481              
482             #adds the directory for the file if it is not in the base
483 0 0         if (defined($cwd)){
484 0           $hash{files}{$line}{cwd}=$cwd;
485             }
486            
487 0           goto contentsParseLoopEnd;
488             }
489             }else {
490 0           goto contentsParseLoopEnd;
491             }
492              
493             #handles a line if it is describing a MD5 of a file
494 0 0         if ($args{file}) {
495 0 0         if ($line =~ /^\@comment MD5:/){
496 0 0         if (!defined($file)){
497 0 0         if (defined($hash{name})){
498 0           $self->warnString('A line matching /^\@comment MD5:/'.
499             ' was found, but no previous files were found. Line="'.
500             $line.'" name="'.$hash{name}.'"');
501             }else {
502 0           $self->warnString('A line matching /^\@comment MD5:/'.
503             ' was found, but no previous files were found. Line="'.$line.'"');
504             }
505             }
506              
507 0           $line =~ s/^\@comment DEPORIGIN://;
508            
509 0           $hash{files}{$file}{MD5}=$line;
510            
511 0           goto contentsParseLoopEnd;
512             }
513             }else {
514 0           goto contentsParseLoopEnd;
515             }
516              
517             #handles unexec lines
518 0 0         if ($line =~ /^\@unexec /){
519 0           $line =~ s/^\@unexec //;
520              
521 0 0         if (!defined($hash{unexec})) {
522 0           $hash{unexec}=[];
523             }
524            
525 0           push(@{$hash{unexec}}, $line);
  0            
526            
527 0           goto contentsParseLoopEnd;
528             }
529              
530             #handles exec lines
531 0 0         if ($line =~ /^\@exec /){
532 0           $line =~ s/^\@exec //;
533              
534 0 0         if (!defined($hash{exec})) {
535 0           $hash{exec}=[];
536             }
537            
538 0           push(@{$hash{exexec}}, $line);
  0            
539            
540 0           goto contentsParseLoopEnd;
541             }
542              
543             #handles unexec lines
544 0 0         if ($line =~ /^\@dirrm /){
545 0           $line =~ s/^\@dirrm //;
546              
547 0 0         if (!defined($hash{dirrm})) {
548 0           $hash{dirrm}=[];
549             }
550            
551 0           push(@{$hash{dirrm}}, $line);
  0            
552            
553 0           goto contentsParseLoopEnd;
554             }
555              
556             #handles display lines
557 0 0         if ($line =~ /^\@display /){
558 0           $line =~ s/^\@display //;
559              
560 0 0         if (!defined($hash{display})) {
561 0           $hash{display}=[];
562             }
563            
564 0           push(@{$hash{display}}, $line);
  0            
565            
566 0           goto contentsParseLoopEnd;
567             }
568              
569             #handles conflict lines
570 0 0         if ($line =~ /^\@conflicts /){
571 0           $line =~ s/^\@conflicts //;
572              
573 0 0         if (!defined($hash{conflict})) {
574 0           $hash{conflict}=[];
575             }
576            
577 0           push(@{$hash{conflict}}, $line);
  0            
578            
579 0           goto contentsParseLoopEnd;
580             }
581              
582             #handles generic comments
583 0 0         if ($line =~ /^\@comment /){
584 0           $line =~ s/^\@comment //;
585              
586 0 0         if (!defined($hash{comment})) {
587 0           $hash{comment}=[];
588             }
589            
590 0           push(@{$hash{comment}}, $line);
  0            
591            
592 0           goto contentsParseLoopEnd;
593             }
594              
595             #if we reach this it means the line was not matched
596 0 0         if (defined($hash{name})){
597 0           warn('FreeBSD-Pkgs parseContents:10: Unmatched line. line="'.$line.
598             '" name="'.$hash{name}.'"');
599             }else{
600 0           warn('FreeBSD-Pkgs parseContents:10: Unmatched line. line="'.$line.
601             '"');
602             }
603              
604             #where using a goto here to simplify checking and speed it up a bit
605 0           contentsParseLoopEnd:
606              
607             $contentsAint++;
608             }
609              
610 0           return %hash;
611             }
612              
613             =head2 parseInstalled
614              
615             This reads all installed packages. The returned value is a boolean.
616              
617             =head3 args hash
618              
619             =head4 files
620              
621             A boolean controlling if file information is parsed or not.
622              
623             This will be passed to parseInstalledPkg and then parseContents.
624              
625             $pkgdb->parseInstalled(%args);
626             #checks to see if it completed successfully
627             if($pkgdb->{error}){
628             print 'Error: '.$pkgdb->{error}."\n";
629             }
630              
631             #checks to make sure it completed successfully using a if statement
632             if($pkgdb->parseInstalled(%args)){
633             print 'Error: '.$pkgdb->{error}."\n";
634             }
635              
636             =cut
637              
638             sub parseInstalled{
639 0     0 1   my $self=$_[0];
640 0           my %args;
641 0 0         if (defined($_[1])) {
642 0           %args=%{$_[1]};
  0            
643             }
644              
645 0 0         if ( ! $self->errorblank ){
646 0           return undef;
647             }
648              
649             #makes sure it exists
650 0 0         if (! -e $self->{pkgdb}){
651 0           $self->{errorString}="PKG_DBDIR, '".$self->{pkgdb}."' does not exist";
652 0           $self->{error}='1';
653 0           $self->warn;
654 0           return undef;
655             }
656              
657             #reads the packages
658 0 0         if (!opendir(PKGDBDIR, $self->{pkgdb})){
659 0           $self->{errorString}="Could not open PKG_DBDIR, '".$self->{pkgdb}."',";
660 0           $self->{error}=2;
661 0           $self->warn;
662 0           return undef;
663             }
664 0           my @packages=readdir(PKGDBDIR);
665 0           closedir(PKGDBDIR);
666              
667             #removes directories that start with '.'
668 0           @packages=grep(!/^\./, @packages);
669              
670             #processes them all
671 0           my $packagesInt=0;
672 0           while (defined($packages[$packagesInt])){
673             #only process it if it is a directory
674 0 0         if (-d $self->{pkgdb}.'/'.$packages[$packagesInt]){
675 0           my %returned=$self->parseInstalledPkg($packages[$packagesInt], \%args);
676             #only add it if it is not an error
677 0 0         if (!defined($self->{error})) {
678 0           $self->{packages}{$packages[$packagesInt]}={%returned};
679              
680             }else{
681 0           $self->warnString('Parsing "'.$packages[$packagesInt].'" as failed.');
682             }
683             }else{
684             #non-fatal
685             #exception for the portupgrade DB file
686 0 0         if ($packages[$packagesInt] ne 'pkgdb.db') {
687 0           $self->warnString('Skipping "'.$packages[$packagesInt].'" as it is not a directory');
688             }
689             }
690              
691 0           $packagesInt++;
692             }
693              
694 0           return 1;
695             }
696              
697             =head2 parseInstalledPkg
698              
699             This parses the specified installed package.
700              
701             =head3 args hash
702              
703             =head4 files
704              
705             A boolean controlling if file information is parsed or not.
706              
707             This will be passed to parseContents.
708              
709             my %pkg=$pkgdb->parseInstalledPkg($pkgname, %args);
710             if($error){
711             print "Error!\n";
712             }
713              
714             =cut
715              
716             sub parseInstalledPkg{
717 0     0 1   my $self=$_[0];
718 0           my $pkg=$_[1];
719 0           my %args;
720 0 0         if (defined($_[2])) {
721 0           %args=%{$_[2]};
  0            
722             }
723              
724 0 0         if (! $self->errorblank ){
725 0           return undef;
726             }
727              
728             #this is the directory that holds the package information
729 0           my $pkgdir=$self->{pkgdb}."/".$pkg;
730              
731 0           my %hash;
732              
733             #the require by file
734 0           my $requiredby=$pkgdir.'/+REQUIRED_BY';
735              
736             #if the required by file exists, process it
737 0 0         if (-f $requiredby){
738             #adds the required by array to the hash
739 0           $hash{requiredby}=[];
740              
741            
742 0 0         if (!open(REQUIREDBY, $requiredby)){
743 0           $self->{error}='4';
744 0           $self->{errorString}='Could not open the required by file, "'.$requiredby.'",';
745 0           $self->warn;
746 0           return undef;
747             }
748 0           my @reqs=;
749 0           close(REQUIREDBY);
750              
751             #processes the required by entries
752 0           my $reqsInt=0;
753 0           while (defined($reqs[$reqsInt])){
754 0           chomp($reqs[$reqsInt]);
755 0           push(@{$hash{requiredby}}, $reqs[$reqsInt]);
  0            
756 0           $reqsInt++;
757             }
758             }
759              
760             #reads the comment
761 0           my $comment=$pkgdir.'/+COMMENT';
762              
763             #opens the comment
764 0 0         if (!open(COMMENT, $comment)) {
765 0           warn('FreeBSD-Pkgs:5: Could not open the comment file, "'.$comment.'"');
766 0           $self->{error}=5;
767 0           return undef;
768             }
769             #reads the comment
770 0           read(COMMENT, $hash{comment}, 32768);
771 0           close(COMMENT);
772 0           chomp($hash{comment});
773              
774             #reads the comment
775 0           my $desc=$pkgdir.'/+DESC';
776              
777             #opens the description
778 0 0         if (!open(DESCRIPTION, $comment)) {
779 0           warn('FreeBSD-Pkgs:6: Could not open the description file, "'.$desc.'"');
780 0           $self->{error}=6;
781 0           return undef;
782             }
783             #reads the comment
784 0           read(DESCRIPTION, $hash{desc}, 32768);
785 0           close(DESCRIPTION);
786              
787              
788             #reads the comment
789 0           my $contents=$pkgdir.'/+CONTENTS';
790              
791             #opens the description
792 0 0         if (!open(CONTENTS, $contents)) {
793 0           warn('FreeBSD-Pkgs:7: Could not open the comment file, "'.$desc.'"');
794 0           $self->{error}=6;
795 0           return undef;
796             }
797             #reads the comment
798 0           my $contentsString;
799 0           read(CONTENTS, $contentsString, 30000000);
800 0           close(CONTENTS);
801              
802             #we don't do any error checking here as if there is a error, it will
803             #already by defined
804 0           $hash{contents}={$self->parseContents($contentsString,\%args)};
805              
806 0           return %hash;
807             }
808              
809             =head1 Package Hash
810              
811             This hash is contained in $pkgdb->{packages} or returned by $pkgdb-parseInstalledPkg.
812             Each of it's key is name of a installed package and a hash. See the information
813             below for key values of that hash.
814              
815             =over
816              
817             =item comment
818              
819             This holds the package comment.
820              
821             =item contents
822              
823             This contains a hash that contains the parsed contents of the '+CONTENTS' file.
824             For additional information on this hash see the section '+CONTENTS Hash'.
825              
826             =item desc
827              
828             This holds the description of the package.
829              
830             =item requiredby
831              
832             This contains a array holding the a list of packages that require this package.
833              
834             =back
835              
836             =head1 +CONTENTS Hash
837              
838             This has is either contained in $pkgdb->{packages}{}{contents} or returned
839             by $pkgdb->parseContents.
840              
841             =over
842              
843             =item cwd
844              
845             This is a string that contains the prefix for the package.
846              
847             =item mtree
848              
849             This is a string that contains the mtree file to use for the package.
850              
851             =item requiredby
852              
853             This is a array that contains a list of packages that requires this package.
854              
855             =item srcdir
856              
857             See pkg_create(1) for @srcdir, as I can't think of a decent description.
858              
859             =item unexec
860              
861             This is a array that contains the unexec lines.
862              
863             =item exec
864              
865             This is a array that contains the exec lines.
866              
867             =item dirrm
868              
869             This is a array of directories to remove.
870              
871             =item conflicts
872              
873             This is a array that holds a list of conflicting packages.
874              
875             =item deps
876              
877             This contains another hash. See the section 'deps Hash' for more information.
878              
879             =item comment
880              
881             This is a array that contains comments that this module was not sure what to do with.
882              
883             =item files
884              
885             This is a hash that contains information on the installed files. See the section 'files
886             Hash' for more information.
887              
888             =back
889              
890             =head1 deps Hash
891              
892             This is a hash contained in $pkgdb->{}{contents}{deps}{}.
893              
894             =over
895              
896             =item origin
897              
898             This is the ports origin location, if one is given.
899              
900             =back
901              
902             =head1 files Hash
903              
904             This is a hash that contains information on the installed files. See the section
905             'files Hash' for more information. This is a hash contained in
906             $pkgdb->{}{contents}{files}{}. The keys of the hash are the name
907             of the files.
908              
909             =over
910              
911             =item MD5
912              
913             This is the MD5 sum of the file.
914              
915             =item cwd
916              
917             This is the cwd for the file if it is not set to the base one.
918              
919             =item ignore_inst
920              
921             This is defined if the ignore_inst flag is set to.
922              
923             =item ignore
924              
925             This is defined if the ignore flag is set to.
926              
927             =item mode
928              
929             This is defined if a specific mode is set for a file.
930              
931             =item group
932              
933             This is defined if a specific group is set for a file.
934              
935             =item owner
936              
937             This is defined if a specific owner is set for a file.
938              
939             =back
940              
941             =head1 NOTES
942              
943             =over
944              
945             =item @noinst
946              
947             These lines in the '+CONTENTS' file are not currently handled.
948              
949             =item @exec
950              
951             The handling of these lines are going to be changed in the near future.
952              
953             =item @unexec
954              
955             The handling of these lines are going to be changed in the near future.
956              
957             =item @display
958              
959             Currently not handled in this version of.
960              
961             =item memory
962              
963             It is generally uses atleast twice the amount of ram as the size of the pkgdb.
964              
965             =back
966              
967             =head1 ERROR CODES/HANDLING
968              
969             Error handling is provided by L.
970              
971             =head2 1
972              
973             PKG_DBDIR does not exist.
974              
975             =head2 2
976              
977             Could not open PKG_DBDIR.
978              
979             =head2 3
980              
981             The named dir entry in PKG_DBDIR is not a directory.
982              
983             =head2 4
984              
985             Could not open the specified required by file.
986              
987             =head2 5
988              
989             Could not open the specified comment file.
990              
991             =head2 6
992              
993             Could not open the specified description file.
994              
995             =head2 7
996              
997             Could not open the specified contents file.
998              
999             =head2 8
1000              
1001             A line matching /^\@comment DEPORIGIN:/ was found, no previous depedencies have
1002             been found.
1003              
1004             =head2 9
1005              
1006             A line matching /^\@comment MD5:/ was found, no previous files have
1007             been found.
1008              
1009             =head2 10
1010              
1011             Unable to make sense of the specified '+CONTENTS' line.
1012              
1013             =head2 11
1014              
1015             /^\@cwd/ matched twice in a '+CONTENTS' file.
1016              
1017             =head1 AUTHOR
1018              
1019             Zane C. Bowers-Hadley, C<< >>
1020              
1021             =head1 BUGS
1022              
1023             Please report any bugs or feature requests to C, or through
1024             the web interface at L. I will be notified, and then you'll
1025             automatically be notified of progress on your bug as I make changes.
1026              
1027              
1028              
1029              
1030             =head1 SUPPORT
1031              
1032             You can find documentation for this module with the perldoc command.
1033              
1034             perldoc FreeBSD::Pkgs
1035              
1036              
1037             You can also look for information at:
1038              
1039             =over 4
1040              
1041             =item * RT: CPAN's request tracker
1042              
1043             L
1044              
1045             =item * AnnoCPAN: Annotated CPAN documentation
1046              
1047             L
1048              
1049             =item * CPAN Ratings
1050              
1051             L
1052              
1053             =item * Search CPAN
1054              
1055             L
1056              
1057             =back
1058              
1059              
1060             =head1 ACKNOWLEDGEMENTS
1061              
1062             Peter V. Vereshagin, #69658, notified me about a pointless warning for the portupgrade DB file
1063              
1064             =head1 COPYRIGHT & LICENSE
1065              
1066             Copyright 2012 Zane C. Bowers-Hadley, all rights reserved.
1067              
1068             This program is free software; you can redistribute it and/or modify it
1069             under the same terms as Perl itself.
1070              
1071              
1072             =cut
1073              
1074             1; # End of FreeBSD::Pkgs