File Coverage

blib/lib/Sys/Info/Driver/Linux/OS.pm
Criterion Covered Total %
statement 139 184 75.5
branch 22 60 36.6
condition 5 29 17.2
subroutine 29 30 96.6
pod 16 16 100.0
total 211 319 66.1


line stmt bran cond sub pod time code
1             package Sys::Info::Driver::Linux::OS;
2             $Sys::Info::Driver::Linux::OS::VERSION = '0.7911';
3 2     2   403420 use strict;
  2         4  
  2         59  
4 2     2   7 use warnings;
  2         4  
  2         114  
5 2     2   7 use parent qw( Sys::Info::Base );
  2         6  
  2         10  
6 2     2   11201 use POSIX ();
  2         14149  
  2         75  
7 2     2   21 use Cwd;
  2         3  
  2         151  
8 2     2   12 use Carp qw( croak );
  2         3  
  2         83  
9 2     2   948 use Sys::Info::Driver::Linux;
  2         6  
  2         104  
10 2     2   957 use Sys::Info::Driver::Linux::Constants qw( :all );
  2         11  
  2         401  
11 2     2   13 use constant FSTAB_LENGTH => 6;
  2         3  
  2         5210  
12              
13             ##no critic (InputOutput::ProhibitBacktickOperators)
14              
15             sub init {
16 1     1 1 1984 my $self = shift;
17 1         7 $self->{OSVERSION} = undef; # see _populate_osversion
18 1         3 $self->{FILESYSTEM} = undef; # see _populate_fs
19 1         2 return;
20             }
21              
22             # unimplemented
23       1 1   sub logon_server {}
24              
25             sub edition {
26 1     1 1 336 return shift->_populate_osversion->{OSVERSION}{RAW}{EDITION};
27             }
28              
29             sub tz {
30 2     2 1 693 my $self = shift;
31 2         11 my $old_tz_file = proc->{timezone_old};
32 2         9 my $tz_file = proc->{timezone};
33 2         4 my $rv;
34              
35 2 50       47 if ( -e $tz_file ) {
    50          
36 0 0       0 if ( ! -l $tz_file ) {
37 0         0 die "The timezone file $tz_file is not a symbolic link!";
38             }
39             else {
40 0         0 my $name = readlink $tz_file;
41 0         0 my $junk = quotemeta '/usr/share/zoneinfo/';
42 0         0 $name =~ s{ \A $junk }{}xmsg;
43 0         0 $rv = $name;
44             }
45             }
46             elsif ( -e $old_tz_file ) {
47 0         0 $rv = chomp( my $rv = $self->slurp( $old_tz_file ) );
48             }
49             else {
50             # warn?
51             }
52              
53 2         10 return $rv;
54             }
55              
56             sub meta {
57 1     1 1 24 my $self = shift->_populate_osversion;
58              
59 1         10 require POSIX;
60 1         4 require Sys::Info::Device;
61              
62 1         21 my $cpu = Sys::Info::Device->new('CPU');
63 1         130 my $arch = ($cpu->identify)[0]->{architecture};
64 1         20 my $model = ($cpu->identify)[0]->{model};
65 1         21 my %mem = $self->_parse_meminfo;
66 1         15 my @swaps = $self->_parse_swap;
67              
68 1 50       8 my $system_type = sprintf '%s based Computer%s',
69             $arch,
70             ( $model ? ". $model" : '' ),
71             ;
72              
73 1         2 my %info;
74              
75 1         6 $info{manufacturer} = $self->{OSVERSION}{MANUFACTURER};
76 1         3 $info{build_type} = undef;
77 1         5 $info{owner} = undef;
78 1         5 $info{organization} = undef;
79 1         3 $info{product_id} = undef;
80 1         4 $info{install_date} = $self->{OSVERSION}{RAW}{BUILD_DATE};
81 1         4 $info{boot_device} = undef;
82              
83 1         4 $info{physical_memory_total} = $mem{MemTotal} * 1024;
84 1         4 $info{physical_memory_available} = $mem{MemFree} * 1024;
85 1         3 $info{page_file_total} = $mem{SwapTotal} * 1024;
86 1         4 $info{page_file_available} = $mem{SwapFree} * 1024;
87              
88             # windows specific
89 1         2 $info{windows_dir} = undef;
90 1         2 $info{system_dir} = undef;
91              
92 1         3 $info{system_manufacturer} = undef;
93 1         2 $info{system_model} = undef;
94 1         3 $info{system_type} = $system_type;
95 1         4 $info{page_file_path} = join ', ', map { $_->{Filename} } @swaps;
  0         0  
96              
97 1         81 return %info;
98             }
99              
100             sub tick_count {
101 2     2 1 4 my $self = shift;
102 2   50     9 my $uptime = $self->slurp( proc->{uptime} ) || return 0;
103 2         236 my @uptime = split /\s+/xms, $uptime;
104             # this file has two entries. uptime is the first one. second: idle time
105 2         14 return $uptime[UP_TIME];
106             }
107              
108             sub name {
109 3     3 1 132 my($self, @args) = @_;
110 3         17 $self->_populate_osversion;
111 3 50       11 my %opt = @args % 2 ? () : @args;
112 3 100       8 my $id = $opt{long} ? 'LONGNAME' : 'NAME';
113 3 100       22 return $self->{OSVERSION}{ $opt{edition} ? $id . '_EDITION' : $id };
114             }
115              
116 1     1 1 4 sub version { return shift->_populate_osversion->{OSVERSION}{VERSION} }
117 1     1 1 4 sub build { return shift->_populate_osversion->{OSVERSION}{RAW}{BUILD_DATE} }
118 1     1 1 7 sub uptime { return time - shift->tick_count }
119              
120             # user methods
121              
122             sub is_root {
123 9     9 1 5202 my $self = shift;
124 9 50       34 return 0 if defined &Sys::Info::EMULATE;
125 9         204 my $id = POSIX::geteuid();
126 9         616 my $gid = POSIX::getegid();
127 9 50       282 return 0 if $@;
128 9 50 33     44 return 0 if ! defined $id || ! defined $gid;
129 9   33     46 return $id == 0 && $gid == 0;
130             }
131              
132             sub login_name {
133 2     2 1 6201 my($self, @args) = @_;
134 2 50       9 my %opt = @args % 2 ? () : @args;
135 2   50     71 my $login = POSIX::getlogin() || return;
136 0         0 my $rv;
137             eval {
138 0 0       0 if ( $opt{real} ) {
139 0         0 $rv = (getpwnam $login)[REAL_NAME_FIELD];
140 0         0 $rv =~ s{ [,]{3,} \z }{}xms;
141 0 0       0 if ( ! $rv ) {
142             # unset, fall back to the loginname
143 0         0 $rv = $login;
144 0         0 delete $opt{real};
145             }
146             }
147 0   0     0 $rv ||= $login;
148 0         0 1;
149 0 0       0 } or do {
150 0   0     0 my $eval_error = $@ || 'Zombie error';
151 0         0 warn sprintf 'Error getting login name: %s', $@;
152 0         0 $rv = $login;
153             };
154 0         0 return $rv;
155             }
156              
157 2     2 1 603 sub node_name { return shift->uname->{nodename} }
158              
159             sub domain_name {
160 2     2 1 1077 my $self = shift;
161             # hmmmm...
162 2         31 foreach my $line ( $self->read_file( proc->{resolv} ) ) {
163 20         412 chomp $line;
164 20 50       46 if ( $line =~ m{\A domain \s+ (.*) \z}xmso ) {
165 0         0 return $1;
166             }
167             }
168 2         13762 my $sys = qx{dnsdomainname 2> /dev/null};
169 2         81 return $sys;
170             }
171              
172             sub fs {
173 1     1 1 5 my $self = shift;
174 1         22 $self->{current_dir} = Cwd::getcwd();
175              
176 1         4 my(@fstab, @junk, $re);
177 1         17 foreach my $line( $self->read_file( proc->{fstab} ) ) {
178 1         388 chomp $line;
179 1 50       10 next if $line =~ m{ \A \# }xms;
180 0         0 @junk = split /\s+/xms, $line;
181 0 0 0     0 next if ! @junk || @junk != FSTAB_LENGTH;
182 0 0       0 next if lc($junk[FS_TYPE]) eq 'swap'; # ignore swaps
183 0         0 $re = $junk[MOUNT_POINT];
184 0 0       0 next if $self->{current_dir} !~ m{\Q$re\E}xmsi;
185 0         0 push @fstab, [ $re, $junk[FS_TYPE] ];
186             }
187              
188 1 50       18 @fstab = reverse sort { $a->[0] cmp $b->[0] } @fstab if @fstab > 1;
  0         0  
189 1         11 my $fstype = $fstab[0]->[1];
190 1         32 my $attr = $self->_fs_attributes( $fstype );
191             return
192             filesystem => $fstype,
193 1 50       34 ($attr ? %{$attr} : ())
  0         0  
194             ;
195             }
196              
197 1 50   1 1 241 sub bitness { return shift->uname->{machine} =~ m{64}xms ? '64' : '32' }
198              
199             # ------------------------[ P R I V A T E ]------------------------ #
200              
201             sub _parse_meminfo {
202 1     1   3 my $self = shift;
203 1         2 my %mem;
204 1         6 foreach my $line ( split /\n/xms, $self->slurp( proc->{meminfo} ) ) {
205 54         590 chomp $line;
206 54         82 my($k, $v) = split /:/xms, $line;
207             # units in KB
208 54         209 $mem{ $k } = (split /\s+/xms, $self->trim( $v ) )[0];
209             }
210 1         50 return %mem;
211             }
212              
213             sub _parse_swap {
214 1     1   2 my $self = shift;
215 1         14 my @swaps = split /\n/xms, $self->slurp( proc->{swaps} );
216 1         108 my @swap_title = split /\s+/xms, shift @swaps;
217 1         2 my @swap_list;
218 1         8 foreach my $line ( @swaps ) {
219 0         0 chomp $line;
220 0         0 my @data = split /\s+/xms, $line;
221             push @swap_list,
222             {
223 0         0 map { $swap_title[$_] => $data[$_] } 0..$#swap_title
  0         0  
224             };
225             }
226 1         3 return @swap_list;
227             }
228              
229             sub _ip {
230 0     0   0 my $self = shift;
231 0         0 my $cmd = q{/sbin/ifconfig};
232 0 0 0     0 return if ! -e $cmd || ! -x _;
233 0         0 my $raw = qx($cmd);
234 0 0       0 return if not $raw;
235 0         0 my @raw = split /inet addr/xms, $raw;
236 0 0 0     0 return if ! @raw || @raw < 2 || ! $raw[1];
      0        
237 0 0       0 if ( $raw[1] =~ m{(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})}xms ) {
238 0         0 return $1;
239             }
240 0         0 return;
241             }
242              
243             sub _populate_osversion {
244 7     7   16 my $self = shift;
245 7 100       41 return $self if $self->{OSVERSION};
246 1         637 require Sys::Info::Driver::Linux::OS::Distribution;
247 1         14 my $distro = Sys::Info::Driver::Linux::OS::Distribution->new;
248 1         8 my $osname = $distro->name;
249 1         4 my $V = $distro->version;
250 1         3 my $edition = $distro->edition;
251 1         7 my $kernel = $distro->kernel;
252 1         4 my $build = $distro->build;
253 1         4 my $build_date = $distro->build_date;
254 1   50     3 my $manufacturer = $distro->manufacturer || q{};
255              
256             $self->{OSVERSION} = {
257 1 50       17 NAME => $osname,
    50          
    50          
258             NAME_EDITION => $edition ? "$osname ($edition)" : $osname,
259             LONGNAME => q{}, # will be set below
260             LONGNAME_EDITION => q{}, # will be set below
261             VERSION => $V,
262             KERNEL => $kernel,
263             MANUFACTURER => $manufacturer,
264             RAW => {
265             BUILD => defined $build ? $build : 0,
266             BUILD_DATE => defined $build_date ? $build_date : 0,
267             EDITION => $edition,
268             },
269             };
270              
271 1         2 my $o = $self->{OSVERSION};
272 1         2 my $t = '%s %s (kernel: %s)';
273 1         6 $o->{LONGNAME} = sprintf $t, $o->{NAME}, $o->{VERSION}, $kernel;
274 1         5 $o->{LONGNAME_EDITION} = sprintf $t, $o->{NAME_EDITION}, $o->{VERSION}, $kernel;
275 1         18 return $self;
276             }
277              
278             sub _fs_attributes {
279 1     1   4 my $self = shift;
280 1         2 my $fs = shift;
281              
282             return {
283             ext3 => {
284             case_sensitive => 1, #'supports case-sensitive filenames',
285             preserve_case => 1, #'preserves the case of filenames',
286             unicode => 1, #'supports Unicode in filenames',
287             #acl => '', #'preserves and enforces ACLs',
288             #file_compression => '', #'supports file-based compression',
289             #disk_quotas => '', #'supports disk quotas',
290             #sparse => '', #'supports sparse files',
291             #reparse => '', #'supports reparse points',
292             #remote_storage => '', #'supports remote storage',
293             #compressed_volume => '', #'is a compressed volume (e.g. DoubleSpace)',
294             #object_identifiers => '', #'supports object identifiers',
295             efs => '1', #'supports the Encrypted File System (EFS)',
296             #max_file_length => '';
297             },
298 1         46 }->{$fs};
299             }
300              
301             1;
302              
303             =pod
304              
305             =encoding UTF-8
306              
307             =head1 NAME
308              
309             Sys::Info::Driver::Linux::OS
310              
311             =head1 VERSION
312              
313             version 0.7911
314              
315             =head1 SYNOPSIS
316              
317             -
318              
319             =head1 DESCRIPTION
320              
321             -
322              
323             =head1 NAME
324              
325             Sys::Info::Driver::Linux::OS - Linux backend
326              
327             =head1 METHODS
328              
329             Please see L<Sys::Info::OS> for definitions of these methods and more.
330              
331             =head2 build
332              
333             =head2 domain_name
334              
335             =head2 edition
336              
337             =head2 fs
338              
339             =head2 init
340              
341             =head2 is_root
342              
343             =head2 login_name
344              
345             =head2 logon_server
346              
347             =head2 meta
348              
349             =head2 name
350              
351             =head2 node_name
352              
353             =head2 tick_count
354              
355             =head2 tz
356              
357             =head2 uptime
358              
359             =head2 version
360              
361             =head2 bitness
362              
363             =head1 SEE ALSO
364              
365             L<Sys::Info>, L<Sys::Info::OS>,
366             The C</proc> virtual filesystem:
367             L<http://www.redhat.com/docs/manuals/linux/RHL-9-Manual/ref-guide/s1-proc-topfiles.html>.
368              
369             =head1 AUTHOR
370              
371             Burak Gursoy
372              
373             =head1 COPYRIGHT AND LICENSE
374              
375             This software is copyright (c) 2006 by Burak Gursoy.
376              
377             This is free software; you can redistribute it and/or modify it under
378             the same terms as the Perl 5 programming language system itself.
379              
380             =cut
381              
382             __END__
383              
384             sub _fetch_user_info {
385             my %user;
386             $user{NAME} = POSIX::getlogin();
387             $user{REAL_USER_ID} = POSIX::getuid(); # $< uid
388             $user{EFFECTIVE_USER_ID} = POSIX::geteuid(); # $> effective uid
389             $user{REAL_GROUP_ID} = POSIX::getgid(); # $( guid
390             $user{EFFECTIVE_GROUP_ID} = POSIX::getegid(); # $) effective guid
391             my %junk;
392             # quota, comment & expire are unreliable
393             @junk{qw(name passwd uid gid
394             quota comment gcos dir shell expire)} = getpwnam($user{NAME});
395             $user{REAL_NAME} = defined $junk{gcos} ? $junk{gcos} : '';
396             $user{COMMENT} = defined $junk{comment} ? $junk{comment} : '';
397             return %user;
398             }
399