File Coverage

blib/lib/Mac/SysProfile.pm
Criterion Covered Total %
statement 12 91 13.1
branch 0 36 0.0
condition 0 26 0.0
subroutine 4 12 33.3
pod 6 7 85.7
total 22 172 12.7


line stmt bran cond sub pod time code
1             package Mac::SysProfile;
2              
3 1     1   27246 use strict;
  1         3  
  1         38  
4 1     1   5 use warnings;
  1         2  
  1         28  
5              
6 1     1   2858 use Mac::PropertyList ();
  1         59519  
  1         22  
7 1     1   11 use Scalar::Util ();
  1         2  
  1         7929  
8              
9             our $VERSION = '0.05';
10              
11             my %conf = (
12             'bin' => 'system_profiler',
13             'lst' => '-listDataTypes',
14             'sfw' => 'SPSoftwareDataType',
15             'sfx' => 'os_overview',
16             'osx' => 'os_version',
17             'drw' => 'kernel_version',
18             'xml' => '-xml',
19             );
20              
21             my %types;
22              
23 0     0 0   sub new { bless {}, shift }
24              
25             sub types {
26 0     0 1   my $pro = shift;
27 0           for (`$conf{bin} $conf{lst}`) {
28 0 0         next if m/:/;
29 0           chomp;
30 0 0         $pro->{$_} = undef unless exists $pro->{$_};
31 0           $types{$_} = 1;
32             }
33 0           return [ keys %types ];
34             }
35              
36             sub gettype {
37 0     0 1   my ( $pro, $typ, $fre ) = @_;
38              
39 0 0         $pro->types() unless exists $types{$typ};
40              
41 0 0         if ( !exists $types{$typ} ) {
42 0           delete $pro->{$typ};
43 0           return;
44             }
45              
46 0 0 0       return $pro->{$typ} if $pro->{$typ} && !$fre;
47              
48 0           my $data = Mac::PropertyList::parse_plist( $pro->xml($typ) );
49 0           my $items = $data->[0]{_items};
50              
51             # Workaround for types that have multiples (e.g. SPMemoryDataType)
52 0 0 0       if ( defined $items->[0] && exists $items->[0]{'_items'} ) {
53 0           $items = $items->[0]{'_items'};
54             }
55              
56 0           my $hdr;
57 0           foreach my $item ( @{$items} ) {
  0            
58 0           my $res;
59              
60 0           my $name = '';
61              
62             # not used to keep from making the already complex structure arbitrarily more complex
63             # would also need done in _structify_val()
64             # my $name = delete $item->{'_name'} || '';
65             # if ( ref($name) ) {
66             # $name = $name->value();
67             # }
68              
69 0           while ( my ( $key, $value ) = each %{$item} ) {
  0            
70 0           my $val = $value->value();
71 0           my $end_val;
72              
73 0 0         if ( ref($val) ) {
74 0           $end_val = $val->value();
75             }
76             else {
77 0           $end_val = $val;
78             }
79              
80 0 0         if ($name) {
81 0           $res->{$name}{$key} = _structify_val($end_val);
82             }
83             else {
84 0           $res->{$key} = _structify_val($end_val);
85             }
86             }
87              
88 0           push @{ $pro->{$typ} }, $res;
  0            
89             }
90              
91 0   0       $pro->{$typ} ||= [];
92              
93 0           return $pro->{$typ};
94             }
95              
96             # recursive fixer upper: Storable::dclone() does not do it, Mac::PropertyList::plist_as_perl() does not seem to work-patches welcome!
97             sub _structify_val {
98 0     0     my ($val) = @_;
99 0           my $ref = Scalar::Util::reftype($val);
100 0 0         return $val if !$ref;
101 0 0         if ( $ref eq 'ARRAY' ) {
    0          
    0          
102 0           my @arr;
103 0           for my $item ( @{$val} ) {
  0            
104 0           push @arr, _structify_val($item);
105             }
106 0           return \@arr;
107             }
108             elsif ( $ref eq 'SCALAR' ) {
109 0           return $val->value();
110             }
111             elsif ( $ref eq 'HASH' ) {
112 0           my %hsh;
113 0           while ( my ( $k, $v ) = each %{$val} ) {
  0            
114 0           $hsh{$k} = _structify_val($v);
115             }
116 0           return \%hsh;
117             }
118             else {
119 0           die "Do not know $ref";
120             }
121             }
122              
123             sub osx {
124 0     0 1   my $pro = shift;
125 0   0       my $fre = shift || '';
126 0 0 0       return $pro->{_osx_version} if $pro->{_osx} && !$fre;
127 0           $pro->gettype( $conf{sfw}, $fre );
128 0           ( $pro->{_osx_version} ) = $pro->{ $conf{sfw} }->{ $conf{sfx} }->{ $conf{osx} } =~ m/\s(\d+(\.\d+)*)\D/;
129 0           return $pro->{_osx_version};
130             }
131              
132             sub darwin {
133 0     0 1   my $pro = shift;
134 0   0       my $fre = shift || '';
135 0 0 0       return $pro->{_darwin_version} if $pro->{_darwin_version} && !$fre;
136 0           $pro->gettype( $conf{sfw}, $fre );
137 0           ( $pro->{_darwin_version} ) = $pro->{ $conf{sfw} }->{ $conf{sfx} }->{ $conf{drw} } =~ m/\s(\d+(\.\d+)*)\D/;
138 0           return $pro->{_darwin_version};
139             }
140              
141             sub state_hashref {
142 0     0 1   my $pro = shift;
143 0           my %x = %{$pro};
  0            
144 0           return \%x;
145             }
146              
147             sub xml {
148 0     0 1   my $pro = shift;
149 0           my $key = shift;
150 0   0       my $fh = shift || '';
151 0 0         my $raw = exists $types{$key} ? `$conf{'bin'} $conf{'xml'} $key` : undef;
152 0 0 0       print $fh $raw if ref $fh eq 'GLOB' && defined $raw;
153 0 0 0       if ( $fh && !ref $fh ) {
154 0 0         open XML, ">$fh" or return;
155 0           print XML $raw;
156 0           close XML;
157             }
158 0           return $raw;
159             }
160              
161             1;
162              
163             __END__