File Coverage

blib/lib/Devel/Platform/Info/Linux.pm
Criterion Covered Total %
statement 28 58 48.2
branch 5 26 19.2
condition 0 3 0.0
subroutine 5 6 83.3
pod 2 2 100.0
total 40 95 42.1


line stmt bran cond sub pod time code
1             package Devel::Platform::Info::Linux;
2              
3 5     5   7728 use strict;
  5         8  
  5         147  
4 5     5   19 use warnings;
  5         4  
  5         112  
5              
6 5     5   16 use vars qw($VERSION);
  5         5  
  5         6960  
7             $VERSION = '0.15';
8              
9             =encoding utf8
10              
11             =head1 NAME
12              
13             Devel::Platform::Info::Linux - Retrieve Linux platform metadata
14              
15             =cut
16              
17             #----------------------------------------------------------------------------
18              
19             my %commands = (
20             '_issue1' => 'cat /etc/issue',
21             '_issue2' => 'cat /etc/.issue',
22             '_uname' => 'uname -a',
23             '_lsb' => 'lsb_release -a',
24             'kname' => 'uname -s',
25             'kvers' => 'uname -r',
26             'osname' => 'uname -o',
27             'archname' => 'uname -m',
28             );
29              
30             my %default = ();
31              
32             # http://en.wikipedia.org/wiki/Arch_Linux#Versions
33             my %archlinux = (
34             '0.1' => 'Homer',
35             '0.2' => 'Vega',
36             '0.3' => 'Firefly',
37             '0.4' => 'Dragon',
38             '0.5' => 'Nova',
39             '0.6' => 'Widget',
40             '0.7' => 'Wombat',
41             '0.8' => 'Voodoo',
42             '2007.05' => 'Duke',
43             '2007.08' => "Don't Panic",
44             '2008.06' => 'Overlord',
45             '2009.02' => '2009.02',
46             '2009.08' => '2009.08',
47             '2010.05' => '2010.05',
48             '2011.08.19' => '2011.08.19',
49             );
50              
51             # previously CrunchBang Linux hasn't normally used codenames, however from
52             # version 10 they are using Debian releases as a base, and thus are using
53             # Muppet Show characters to compliment the Toy Story characters as used by
54             # Debian.
55              
56             my %crunch = (
57             '8.04.02' => 'Back in Black',
58             '10' => 'Statler',
59             '11' => 'Waldorf',
60             );
61              
62             # http://en.wikipedia.org/wiki/Debian#Release_history
63             my %debian = (
64             '1.1' => 'buzz',
65             '1.2' => 'rex',
66             '1.3' => 'bo',
67             '2.0' => 'hamm',
68             '2.1' => 'slink',
69             '2.2' => 'potato',
70             '3.0' => 'woody',
71             '3.1' => 'sarge',
72             '4.0' => 'etch',
73             '5.0' => 'lenny',
74             '6.0' => 'squeeze',
75             '7.0' => 'wheezy',
76             '8.0' => 'jessie',
77             );
78              
79             # Fedora naming scheme is no longer used:
80             # https://lists.fedoraproject.org/pipermail/advisory-board/2013-October/012209.html
81             # "The Fedora Board is terminating Release Names as they are currently
82             # fashioned following Fedora 20."
83              
84             # http://en.wikipedia.org/wiki/Fedora_%28operating_system%29#Version_history
85             my %fedora = (
86             '1' => 'Yarrow',
87             '2' => 'Tettnang',
88             '3' => 'Heidelberg',
89             '4' => 'Stentz',
90             '5' => 'Bordeaux',
91             '6' => 'Zod',
92             '7' => 'Moonshine',
93             '8' => 'Werewolf',
94             '9' => 'Sulphur',
95             '10' => 'Cambridge',
96             '11' => 'Leonidas',
97             '12' => 'Constantine',
98             '13' => 'Goddard',
99             '14' => 'Laughlin',
100             '15' => 'Lovelock',
101             '16' => 'Verne',
102             '17' => 'Beefy Miracle',
103             '18' => 'Spherical Cow',
104             '19' => q[Schrödinger's Cat],
105             '20' => 'Heisenbug',
106             );
107              
108             # http://en.wikipedia.org/wiki/Mandriva_Linux#Versions
109             my %mandriva = (
110             '5.1' => 'Venice',
111             '5.2' => 'Leeloo',
112             '5.3' => 'Festen',
113             '6.0' => 'Venus',
114             '6.1' => 'Helios',
115             '7.0' => 'Air',
116             '7.1' => 'Helium',
117             '7.2' => 'Odyssey (called Ulysses during beta)',
118             '8.0' => 'Traktopel',
119             '8.1' => 'Vitamin',
120             '8.2' => 'Bluebird',
121             '9.0' => 'Dolphin',
122             '9.1' => 'Bamboo',
123             '9.2' => 'FiveStar',
124             '10.0' => 'Community and Official',
125             '10.1' => 'Community',
126             '10.1' => 'Official',
127             '10.2' => 'Limited Edition 2005',
128             '2006.0' => 'Mandriva Linux 2006',
129             '2007' => 'Mandriva Linux 2007',
130             '2007.1' => 'Mandriva Linux 2007 Spring',
131             '2008.0' => 'Mandriva Linux 2008',
132             '2008.1' => 'Mandriva Linux 2008 Spring',
133             '2009.0' => 'Mandriva Linux 2009',
134             '2009.1' => 'Mandriva Linux 2009 Spring',
135             '2010.0' => 'Mandriva Linux 2010 (Adélie)',
136             '2010.1' => 'Mandriva Linux 2010 Spring',
137             '2010.2' => 'Mandriva Linux 2010.2',
138             '2011.0' => 'Hydrogen',
139             );
140              
141             # http://en.wikipedia.org/wiki/Red_Hat_Linux#Version_history
142             # http://fedoraproject.org/wiki/History_of_Red_Hat_Linux
143             my %redhat = (
144             '0.8' => 'Preview',
145             '0.9' => 'Halloween',
146             '1.0' => q{Mother's Day},
147             '1.1' => q{Mother's Day+0.1},
148             '2.0' => '',
149             '2.1' => '',
150             '3.0.3' => 'Picasso',
151             '3.95' => 'Rembrandt',
152             '4.0' => 'Colgate',
153             '4.1' => 'Vanderbilt',
154             '4.2' => 'Biltmore',
155             '4.95' => 'Thunderbird',
156             '4.96' => 'Mustang',
157             '5.0' => 'Hurricane',
158             '5.1' => 'Manhattan',
159             '5.2' => 'Apollo',
160             '5.9' => 'Starbuck',
161             '6.0' => 'Hedwig',
162             '6.0.95' => 'Lorax',
163             '6.1' => 'Cartman',
164             '6.1.95' => 'Piglet',
165             '6.2' => 'Zoot',
166             '6.2.98' => 'Pinstripe',
167             '7' => 'Guinness',
168             '7.0.90' => 'Fisher',
169             '7.0.91' => 'Wolverine',
170             '7.1' => 'Seawolf',
171             '7.1.92' => 'Roswell',
172             '7.2' => 'Enigma',
173             '7.2.92' => 'Skipjack',
174             '7.3' => 'Valhalla',
175             '7.3.92' => 'Limbo',
176             '7.3.93' => 'Limbo',
177             '7.3.94' => 'Null',
178             '8.0' => 'Psyche',
179             '8.0.93' => 'Phoebe',
180             '9' => 'Shrike',
181             '9.0.93' => 'Severn',
182             );
183              
184             # http://en.wikipedia.org/wiki/Red_Hat_Enterprise_Linux#Version_history
185             my %rhel = (
186             '2.1 AS' => 'Pensacola',
187             '2.1' => 'Pensacola',
188             '2.1.1' => 'Pensacola',
189             '2.1.2' => 'Pensacola',
190             '2.1.3' => 'Pensacola',
191             '2.1.4' => 'Pensacola',
192             '2.1.5' => 'Pensacola',
193             '2.1.6' => 'Pensacola',
194             '2.1.7' => 'Pensacola',
195             '2.1 ES' => 'Panama',
196             '3' => 'Taroon',
197             '3.0' => 'Taroon',
198             '3.1' => 'Taroon',
199             '3.2' => 'Taroon',
200             '3.3' => 'Taroon',
201             '3.4' => 'Taroon',
202             '3.5' => 'Taroon',
203             '3.6' => 'Taroon',
204             '3.7' => 'Taroon',
205             '3.8' => 'Taroon',
206             '3.9' => 'Taroon',
207             '4' => 'Nahant',
208             '4.1' => 'Nahant',
209             '4.2' => 'Nahant',
210             '4.3' => 'Nahant',
211             '4.4' => 'Nahant',
212             '4.5' => 'Nahant',
213             '4.6' => 'Nahant',
214             '4.7' => 'Nahant',
215             '4.8' => 'Nahant',
216             '4.9' => 'Nahant',
217             '5' => 'Tikanga',
218             '5.1' => 'Tikanga',
219             '5.2' => 'Tikanga',
220             '5.3' => 'Tikanga',
221             '5.4' => 'Tikanga',
222             '5.5' => 'Tikanga',
223             '5.6' => 'Tikanga',
224             '5.7' => 'Tikanga',
225             '5.8' => 'Tikanga',
226             '6' => 'Santiago',
227             '6.1' => 'Santiago',
228             '6.2' => 'Santiago',
229             '6.3' => 'Santiago',
230             '6.4' => 'Santiago',
231             '6.5' => 'Santiago',
232             '7' => 'Maipo',
233             );
234              
235             # http://en.wikipedia.org/wiki/Scientific_Linux
236             my %scientific = (
237             '3.0.1' => 'Feynman',
238             '3.0.2' => 'Feynman',
239             '3.0.3' => 'Feynman',
240             '3.0.4' => 'Feynman',
241             '3.0.5' => 'Feynman',
242             '3.0.6' => 'Feynman',
243             '3.0.7' => 'Feynman',
244             '3.0.8' => 'Feynman',
245             '3.0.9' => 'Legacy',
246             '4.0' => 'Beryllium',
247             '4.1' => 'Beryllium',
248             '4.2' => 'Beryllium',
249             '4.3' => 'Beryllium',
250             '4.4' => 'Beryllium',
251             '4.5' => 'Beryllium',
252             '4.6' => 'Beryllium',
253             '4.7' => 'Beryllium',
254             '4.8' => 'Beryllium',
255             '4.9' => 'Beryllium',
256             '5.0' => 'Boron',
257             '5.1' => 'Boron',
258             '5.2' => 'Boron',
259             '5.3' => 'Boron',
260             '5.4' => 'Boron',
261             '5.5' => 'Boron',
262             '5.6' => 'Boron',
263             '5.7' => 'Boron',
264             '5.8' => 'Boron',
265             '5.9' => 'Boron',
266             '6.0' => 'Carbon',
267             '6.1' => 'Carbon',
268             '6.2' => 'Carbon',
269             '6.3' => 'Carbon',
270             );
271              
272             # http://en.wikipedia.org/wiki/Ubuntu_%28operating_system%29#Releases
273             my %ubuntu = (
274             '4.10' => 'Warty Warthog',
275             '5.04' => 'Hoary Hedgehog',
276             '5.10' => 'Breezy Badger',
277             '6.06' => 'Dapper Drake',
278             '6.10' => 'Edgy Eft',
279             '7.04' => 'Feisty Fawn',
280             '7.10' => 'Gutsy Gibbon',
281             '8.04' => 'Hardy Heron',
282             '8.10' => 'Intrepid Ibex',
283             '9.04' => 'Jaunty Jackalope',
284             '9.10' => 'Karmic Koala',
285             '10.04' => 'Lucid Lynx',
286             '10.10' => 'Maverick Meerkat',
287             '11.04' => 'Natty Narwhal',
288             '11.10' => 'Oneiric Ocelot',
289             '12.04' => 'Precise Pangolin',
290             '12.10' => 'Quantal Quetzal',
291             '13.04' => 'Raring Ringtail',
292             '13.10' => 'Saucy Salamander',
293             '14.04' => 'Trusty Tahr',
294             '14.10' => 'Utopic Unicorn',
295             );
296              
297             my %distributions = (
298             'Adamantix' => { codenames => \%default, files => [ qw( /etc/adamantix_version ) ] },
299             'Annvix' => { codenames => \%default, files => [ qw( /etc/annvix-release ) ] },
300             'Arch Linux' => { codenames => \%archlinux, files => [ qw( /etc/arch-release ) ] },
301             'Arklinux' => { codenames => \%default, files => [ qw( /etc/arklinux-release ) ] },
302             'Aurox Linux' => { codenames => \%default, files => [ qw( /etc/aurox-release ) ] },
303             'BlackCat' => { codenames => \%default, files => [ qw( /etc/blackcat-release ) ] },
304             'Cobalt' => { codenames => \%default, files => [ qw( /etc/cobalt-release ) ] },
305             'Conectiva' => { codenames => \%default, files => [ qw( /etc/conectiva-release ) ] },
306             'CrunchBang Linux' => { codenames => \%crunch, files => [ qw( /etc/lsb-release-crunchbang /etc/lsb-release ) ] },
307             'Debian' => { codenames => \%debian, key => 'debian', files => [ qw( /etc/debian_version /etc/debian_release ) ] },
308             'Fedora Core' => { codenames => \%fedora, key => 'fedora', files => [ qw( /etc/fedora-release ) ] },
309             'Gentoo Linux' => { codenames => \%default, key => 'gentoo', files => [ qw( /etc/gentoo-release ) ] },
310             'Immunix' => { codenames => \%default, files => [ qw( /etc/immunix-release ) ] },
311             'Knoppix' => { codenames => \%default, files => [ qw( /etc/knoppix_version ) ] },
312             'Libranet' => { codenames => \%default, files => [ qw( /etc/libranet_version ) ] },
313             'Linux-From-Scratch' => { codenames => \%default, files => [ qw( /etc/lfs-release ) ] },
314             'Linux-PPC' => { codenames => \%default, files => [ qw( /etc/linuxppc-release ) ] },
315             'Mandrake' => { codenames => \%mandriva, files => [ qw( /etc/mandrake-release ) ] },
316             'Mandriva' => { codenames => \%mandriva, files => [ qw( /etc/mandriva-release /etc/mandrake-release /etc/mandakelinux-release ) ] },
317             'Mandrake Linux' => { codenames => \%mandriva, files => [ qw( /etc/mandriva-release /etc/mandrake-release /etc/mandakelinux-release ) ] },
318             'MkLinux' => { codenames => \%default, files => [ qw( /etc/mklinux-release ) ] },
319             'Novell Linux Desktop' => { codenames => \%default, files => [ qw( /etc/nld-release ) ] },
320             'Pardus' => { codenames => \%default, key => 'pardus', files => [ qw( /etc/pardus-release ) ] },
321             'PLD Linux' => { codenames => \%default, files => [ qw( /etc/pld-release ) ] },
322             'Red Flag' => { codenames => \%default, key => 'redflag', files => [ qw( /etc/redflag-release ) ] },
323             'Red Hat Enterprise Linux' => { codenames => \%rhel, key => 'rhel', files => [ qw( /etc/redhat-release /etc/redhat_version ) ] },
324             'Red Hat Linux' => { codenames => \%redhat, key => 'redhat', files => [ qw( /etc/redhat-release /etc/redhat_version ) ] },
325             'Scientific Linux' => { codenames => \%scientific, files => [ qw( /etc/lsb-release ) ] },
326             'Slackware' => { codenames => \%default, key => 'slackware', files => [ qw( /etc/slackware-version /etc/slackware-release ) ] },
327             'SME Server' => { codenames => \%default, files => [ qw( /etc/e-smith-release ) ] },
328             'Sun JDS' => { codenames => \%default, files => [ qw( /etc/sun-release ) ] },
329             'SUSE Linux' => { codenames => \%default, key => 'suse', files => [ qw( /etc/SuSE-release /etc/novell-release ) ] },
330             'SUSE Linux ES9' => { codenames => \%default, key => 'suse', files => [ qw( /etc/sles-release ) ] },
331             'Tiny Sofa' => { codenames => \%default, files => [ qw( /etc/tinysofa-release ) ] },
332             'Trustix Secure Linux' => { codenames => \%default, files => [ qw( /etc/trustix-release ) ] },
333             'TurboLinux' => { codenames => \%default, files => [ qw( /etc/turbolinux-release ) ] },
334             'Ubuntu Linux' => { codenames => \%ubuntu, files => [ qw( /etc/lsb-release ) ] },
335             'UltraPenguin' => { codenames => \%default, files => [ qw( /etc/ultrapenguin-release ) ] },
336             'UnitedLinux' => { codenames => \%default, files => [ qw( /etc/UnitedLinux-release ) ] },
337             'VA-Linux/RH-VALE' => { codenames => \%default, files => [ qw( /etc/va-release ) ] },
338             'Yellow Dog' => { codenames => \%default, files => [ qw( /etc/yellowdog-release ) ] },
339             'Yoper' => { codenames => \%default, files => [ qw( /etc/yoper-release ) ] },
340             );
341              
342             my %version_pattern = (
343             'gentoo' => 'Gentoo Base System version (.*)',
344             'debian' => '(.+)',
345             'suse' => 'VERSION = (.*)',
346             'fedora' => 'Fedora Core release (\d+) \(',
347             'redflag' => 'Red Flag (?:Desktop|Linux) (?:release |\()(.*?)(?: \(.+)?\)',
348             'redhat' => 'Red Hat Linux release (.*) \(',
349             'rhel' => 'Red Hat Enterprise Linux(?: Server)? release (.*) \(',
350             'slackware' => '^Slackware (.+)$',
351             'pardus' => '^Pardus (.+)$',
352             );
353              
354             my %oslabel_pattern = (
355             'suse' => '^(\S+)',
356             'rhel' => '(Red Hat Enterprise Linux(?: Server)?) release (.*) \(',
357             );
358              
359             #----------------------------------------------------------------------------
360              
361             sub new {
362 1     1 1 1 my ($class) = @_;
363 1         1 my $self = {};
364 1         2 bless $self, $class;
365              
366 1         7 return $self;
367             }
368              
369             sub get_info {
370 1     1 1 1 my $self = shift;
371              
372 1         4 for my $cmd (keys %commands) {
373 8         99372 $self->{cmds}{$cmd} = `$commands{$cmd} 2>/dev/null`;
374 8         199 $self->{cmds}{$cmd} =~ s/\s+$//s;
375 8 100       155 $self->{info}{$cmd} = $self->{cmds}{$cmd} if($cmd !~ /^_/);
376             }
377              
378 1         22 $self->{info}{osflag} = $^O;
379 1         9 $self->{info}{kernel} = lc($self->{info}{kname}) . '-' . $self->{info}{kvers};
380              
381 1 50       20 $self->{info}{is32bit} = $self->{info}{archname} !~ /_(64)$/ ? 1 : 0;
382 1 50       20 $self->{info}{is64bit} = $self->{info}{archname} =~ /_(64)$/ ? 1 : 0;
383              
384 1 50       8 if($self->{cmds}{'_lsb'}) {
385 1         15 ($self->{info}{oslabel}) = $self->{cmds}{'_lsb'} =~ /Distributor ID:\s*(.*?)\n/si;
386 1         12 ($self->{info}{osvers}) = $self->{cmds}{'_lsb'} =~ /Release:\s*(.*?)\n/si;
387 1         11 ($self->{info}{codename}) = $self->{cmds}{'_lsb'} =~ /Codename:\s*(.*)\n?/si;
388             } else {
389 0         0 $self->_release_version();
390             }
391              
392 1         34 $self->{info}{source}{$commands{$_}} = $self->{cmds}{$_} for(keys %commands);
393 1         22 return $self->{info};
394             }
395              
396             #----------------------------------------------------------------------------
397              
398             sub _release_version {
399 0     0     my $self = shift;
400              
401 0           for my $label (keys %distributions) {
402 0           for my $file (@{ $distributions{$label}->{files} }) {
  0            
403 0 0         next unless(-f $file);
404 0           my $line = `cat $file 2>/dev/null`;
405              
406 0           my ($version,$oslabel);
407 0 0         if($distributions{$label}->{key}) {
408 0 0         if($version_pattern{ $distributions{$label}->{key} }) {
409 0           ($version) = $line =~ /$version_pattern{ $distributions{$label}->{key} }/si;
410             }
411 0 0         if($oslabel_pattern{ $distributions{$label}->{key} }) {
412 0           ($oslabel) = $line =~ /$oslabel_pattern{ $distributions{$label}->{key} }/si;
413             }
414             }
415              
416 0 0         $version = $line unless($version);
417 0           $version =~ s/\s*$//;
418              
419 0 0         unless($oslabel) {
420 0 0         if($self->{cmds}{'_issue1'}) {
    0          
421 0           ($oslabel) = $self->{cmds}{'_issue1'} =~ /^(\S*)/;
422             } elsif($self->{cmds}{'_issue2'}) {
423 0           ($oslabel) = $self->{cmds}{'_issue2'} =~ /^(\S*)/;
424             }
425 0   0       $oslabel ||= $label; # a last resort
426             }
427              
428 0           $self->{info}{oslabel} = $oslabel;
429 0           $self->{info}{osvers} = $version;
430 0           $commands{'_cat'} = "cat $file";
431 0           $self->{cmds}{'_cat'} = $line;
432              
433 0           for my $vers (keys %{ $distributions{$label}->{codenames} }) {
  0            
434 0 0         if($version =~ /^$vers\b/) {
435 0           $self->{info}{codename} = $distributions{$label}->{codenames}{$vers};
436 0           return;
437             }
438             }
439              
440 0           return;
441             }
442             }
443             }
444              
445             1;
446              
447             __END__