source: ProjectBuilder/devel/pb-modules/lib/ProjectBuilder/Distribution.pm@ 620

Last change on this file since 620 was 620, checked in by Bruno Cornec, 15 years ago
  • change pb_distro_init interface and add a 6th parameter which is the update CLI to use for that distro.
File size: 10.3 KB
Line 
1#!/usr/bin/perl -w
2#
3# Creates common environment for distributions
4#
5# $Id$
6#
7
8package ProjectBuilder::Distribution;
9
10use strict;
11use Data::Dumper;
12use ProjectBuilder::Base;
13
14# Inherit from the "Exporter" module which handles exporting functions.
15
16use Exporter;
17
18# Export, by default, all the functions into the namespace of
19# any code which uses this module.
20
21our @ISA = qw(Exporter);
22our @EXPORT = qw(pb_distro_init pb_get_distro);
23
24=pod
25
26=head1 NAME
27
28ProjectBuilder::Distribution, part of the project-builder.org - module dealing with distribution detection
29
30=head1 DESCRIPTION
31
32This modules provides functions to allow detection of Linux distributions, and giving back some attributes concerning them.
33
34=head1 SYNOPSIS
35
36 use ProjectBuilder::Distribution;
37
38 #
39 # Return information on the running distro
40 #
41 my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init();
42 print "distro tuple: ".Dumper($ddir, $dver, $dfam, $dtype, $pbsuf)."\n";
43 #
44 # Return information on the requested distro
45 #
46 my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init("ubuntu","7.10");
47 print "distro tuple: ".Dumper($ddir, $dver, $dfam, $dtype, $pbsuf)."\n";
48 #
49 # Return information on the running distro
50 #
51 my ($ddir,$dver) = pb_get_distro();
52 my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init($ddir,$dver);
53 print "distro tuple: ".Dumper($ddir, $dver, $dfam, $dtype, $pbsuf)."\n";
54
55=head1 USAGE
56
57=over 4
58
59
60=item B<pb_get_distro>
61
62This function returns a list of 2 parameters indicating the distribution name and version of the underlying Linux distribution. The value of those 2 fields may be "unknown" in case the function was unable to recognize on which distribution it is running.
63
64On my home machine it would currently report ("mandriva","2008.0").
65
66=cut
67
68sub pb_distro_init {
69
70my $ddir = shift || undef;
71my $dver = shift || undef;
72my $dfam = "unknown";
73my $dtype = "unknown";
74my $dsuf = "unknown";
75my $dupd = "unknown";
76
77# If we don't know which distribution we're on, then guess it
78($ddir,$dver) = pb_get_distro() if ((not defined $ddir) || (not defined $dver));
79
80# There should be unicity of names between ddir dfam and dtype
81# In case of duplicate, bad things can happen
82if (($ddir =~ /debian/) ||
83 ($ddir =~ /ubuntu/)) {
84 $dfam="du";
85 $dtype="deb";
86 $dsuf=".$ddir$dver";
87 $dupd="apt-get -y install ";
88} elsif ($ddir =~ /gentoo/) {
89 $dfam="gen";
90 $dtype="ebuild";
91 $dver="nover";
92 $dsuf=".$ddir";
93 $dupd="emerge ";
94} elsif ($ddir =~ /slackware/) {
95 $dfam="slack";
96 $dtype="tgz";
97 $dsuf=".$dfam$dver";
98} elsif (($ddir =~ /suse/) ||
99 ($ddir =~ /sles/)) {
100 if ($ddir =~ /opensuse/) {
101 $ddir = "suse";
102 }
103 $dfam="novell";
104 $dtype="rpm";
105 $dsuf=".$ddir$dver";
106 $dupd="yast2 -y ";
107} elsif (($ddir =~ /redhat/) ||
108 ($ddir =~ /rhel/) ||
109 ($ddir =~ /fedora/) ||
110 ($ddir =~ /vmware/) ||
111 ($ddir =~ /centos/)) {
112 $dfam="rh";
113 $dtype="rpm";
114 my $dver1 = $dver;
115 $dver1 =~ s/\.//;
116
117 # By defaut propose yum
118 my $arch=`uname -m`;
119 my $opt = "";
120 chomp($arch);
121 if ($arch eq "x86_64") {
122 $opt="--exclude=*.i?86";
123 }
124 $dupd="yum -y $opt install ";
125 if ($ddir =~ /fedora/) {
126 $dsuf=".fc$dver1";
127 } elsif ($ddir =~ /redhat/) {
128 $dsuf=".rh$dver1";
129 $dupd="unknown";
130 } elsif ($ddir =~ /vmware/) {
131 $dsuf=".vwm$dver1";
132 $dupd="unknown";
133 } else {
134 # older versions of rhel and centos ran up2date
135 if (($dver eq "2.1") || ($dver eq "3") || ($dver eq "4")) {
136 $dupd="up2date -y ";
137 }
138 $dsuf=".$ddir$dver1";
139 }
140} elsif (($ddir =~ /mandrake/) ||
141 ($ddir =~ /mandrakelinux/) ||
142 ($ddir =~ /mandriva/)) {
143 $dfam="md";
144 $dtype="rpm";
145 if ($ddir =~ /mandrakelinux/) {
146 $ddir = "mandrake";
147 }
148 if ($ddir =~ /mandrake/) {
149 my $dver1 = $dver;
150 $dver1 =~ s/\.//;
151 $dsuf=".mdk$dver1";
152 } else {
153 $dsuf=".mdv$dver";
154 }
155 $dupd="urpmi --auto ";
156} elsif ($ddir =~ /freebsd/) {
157 $dfam="bsd";
158 $dtype="port";
159 my $dver1 = $dver;
160 $dver1 =~ s/\.//;
161 $dsuf=".$dfam$dver1";
162} else {
163 $dfam="unknown";
164}
165
166return($ddir, $dver, $dfam, $dtype, $dsuf, $dupd);
167}
168
169=item B<pb_distro_init>
170
171This function returns a list of 5 parameters indicating the distribution name, version, family, type of build system and suffix of packages of the underlying Linux distribution. The value of the 5 fields may be "unknown" in case the function was unable to recognize on which distribution it is running.
172
173As an example, Ubuntu and Debian are in the same "du" family. As well as RedHat, RHEL, CentOS, fedora are on the same "rh" family.
174Mandriva, Open SuSE and Fedora have all the same "rpm" type of build system. Ubuntu ad Debian have the same "deb" type of build system.
175And "fc" is the extension generated for all Fedora packages (Version will be added by pb).
176
177When passing the distribution name and version as parameters, the B<pb_distro_init> function returns the parameter of that distribution instead of the underlying one.
178
179Cf: http://linuxmafia.com/faq/Admin/release-files.html
180Ideas taken from http://search.cpan.org/~kerberus/Linux-Distribution-0.14/lib/Linux/Distribution.pm
181
182=cut
183
184sub pb_get_distro {
185
186my $base="/etc";
187
188# List of files that unambiguously indicates what distro we have
189my %single_rel_files = (
190# Tested
191 'gentoo' => 'gentoo-release', # >= 1.6
192 'slackware' => 'slackware-version', # >= 10.2
193 'mandriva' => 'mandriva-release', # >=2006.0
194 'mandrakelinux' => 'mandrakelinux-release',# = 10.2
195 'fedora' => 'fedora-release', # >= 4
196 'vmware' => 'vmware-release', # >= 3
197 'sles' => 'sles-release', # Doesn't exist as of 10
198# Untested
199 'knoppix' => 'knoppix_version', #
200 'yellowdog' => 'yellowdog-release', #
201 'esmith' => 'e-smith-release', #
202 'turbolinux' => 'turbolinux-release', #
203 'blackcat' => 'blackcat-release', #
204 'aurox' => 'aurox-release', #
205 'annvix' => 'annvix-release', #
206 'cobalt' => 'cobalt-release', #
207 'redflag' => 'redflag-release', #
208 'ark' => 'ark-release', #
209 'pld' => 'pld-release', #
210 'nld' => 'nld-release', #
211 'lfs' => 'lfs-release', #
212 'mk' => 'mk-release', #
213 'conectiva' => 'conectiva-release', #
214 'immunix' => 'immunix-release', #
215 'tinysofa' => 'tinysofa-release', #
216 'trustix' => 'trustix-release', #
217 'adamantix' => 'adamantix_version', #
218 'yoper' => 'yoper-release', #
219 'arch' => 'arch-release', #
220 'libranet' => 'libranet_version', #
221 'valinux' => 'va-release', #
222 'yellowdog' => 'yellowdog-release', #
223 'ultrapenguin' => 'ultrapenguin-release', #
224 );
225
226# List of files that ambiguously indicates what distro we have
227my %ambiguous_rel_files = (
228 'mandrake' => 'mandrake-release', # <= 10.1
229 'debian' => 'debian_version', # >= 3.1
230 'suse' => 'SuSE-release', # >= 10.0
231 'redhat' => 'redhat-release', # >= 7.3
232 'lsb' => 'lsb-release', # ???
233 );
234
235# Should have the same keys as the previous one.
236# If ambiguity, which other distributions should be checked
237my %distro_similar = (
238 'mandrake' => ['mandrake', 'mandrakelinux'],
239 'debian' => ['debian', 'ubuntu'],
240 'suse' => ['suse', 'sles', 'opensuse'],
241 'redhat' => ['redhat', 'rhel', 'centos', 'mandrake', 'vmware'],
242 'lsb' => ['ubuntu', 'lsb'],
243 );
244
245my %distro_match = (
246# Tested
247 'gentoo' => '.* version (.+)',
248 'slackware' => 'S[^ ]* (.+)$',
249# There should be no ambiguity between potential ambiguous distro
250 'mandrakelinux' => 'Mandrakelinux release (.+) \(',
251 'mandrake' => 'Mandr[^ ]* release (.+) \(',
252 'mandriva' => 'Mandr[^ ]* [^ ]* release (.+) \(',
253 'fedora' => 'Fedora .*release (\d+) \(',
254 'vmware' => 'VMware ESX Server (\d+) \(',
255 'rhel' => 'Red Hat (?:Enterprise Linux|Linux Advanced Server) .*release ([0-9.]+).* \(',
256 'centos' => '.*CentOS .*release (.+) ',
257 'redhat' => 'Red Hat Linux release (.+) \(',
258 'sles' => 'SUSE .* Enterprise Server (\d+) \(',
259 'suse' => 'SUSE LINUX (\d.+) \(',
260 'opensuse' => 'openSUSE (\d.+) \(',
261 'lsb' => '.*[^Ubunt].*\nDISTRIB_RELEASE=(.+)',
262# Ubuntu includes a /etc/debian_version file that cretaes an ambiguity with debian
263# So we need to look at distros in reverse alphabetic order to treat ubuntu always first
264 'ubuntu' => '.*Ubuntu.*\nDISTRIB_RELEASE=(.+)',
265 'debian' => '(.+)',
266# Not tested
267 'arch' => '.* ([0-9.]+) .*',
268 'redflag' => 'Red Flag (?:Desktop|Linux) (?:release |\()(.*?)(?: \(.+)?\)',
269);
270
271my $release;
272my $distro;
273
274# Begin to test presence of non-ambiguous files
275# that way we reduce the choice
276my ($d,$r);
277while (($d,$r) = each %single_rel_files) {
278 if (-f "$base/$r" && ! -l "$base/$r") {
279 my $tmp=pb_get_content("$base/$r");
280 # Found the only possibility.
281 # Try to get version and return
282 if (defined ($distro_match{$d})) {
283 ($release) = $tmp =~ m/$distro_match{$d}/m;
284 } else {
285 print STDERR "Unable to find $d version in $r\n";
286 print STDERR "Please report to the maintainer bruno_at_project-builder.org\n";
287 $release = "unknown";
288 }
289 return($d,$release);
290 }
291}
292
293# Now look at ambiguous files
294# Ubuntu includes a /etc/debian_version file that creates an ambiguity with debian
295# So we need to look at distros in reverse alphabetic order to treat ubuntu always first via lsb
296foreach $d (reverse keys %ambiguous_rel_files) {
297 $r = $ambiguous_rel_files{$d};
298 if (-f "$base/$r" && !-l "$base/$r") {
299 # Found one possibility.
300 # Get all distros concerned by that file
301 my $tmp=pb_get_content("$base/$r");
302 my $found = 0;
303 my $ptr = $distro_similar{$d};
304 pb_log(2,"amb: ".Dumper($ptr)."\n");
305 $release = "unknown";
306 foreach my $dd (@$ptr) {
307 pb_log(2,"check $dd\n");
308 # Try to check pattern
309 if (defined $distro_match{$dd}) {
310 pb_log(2,"cmp: $distro_match{$dd} - vs - $tmp\n");
311 ($release) = $tmp =~ m/$distro_match{$dd}/m;
312 if ((defined $release) && ($release ne "unknown")) {
313 $distro = $dd;
314 $found = 1;
315 last;
316 }
317 }
318 }
319 if ($found == 0) {
320 print STDERR "Unable to find $d version in $r\n";
321 print STDERR "Please report to the maintainer bruno_at_project-builder.org\n";
322 $release = "unknown";
323 } else {
324 return($distro,$release);
325 }
326 }
327}
328return("unknown","unknown");
329}
330
331=back
332
333=head1 WEB SITES
334
335The main Web site of the project is available at L<http://www.project-builder.org/>. Bug reports should be filled using the trac instance of the project at L<http://trac.project-builder.org/>.
336
337=head1 USER MAILING LIST
338
339None exists for the moment.
340
341=head1 AUTHORS
342
343The Project-Builder.org team L<http://trac.project-builder.org/> lead by Bruno Cornec L<mailto:bruno@project-builder.org>.
344
345=head1 COPYRIGHT
346
347Project-Builder.org is distributed under the GPL v2.0 license
348described in the file C<COPYING> included with the distribution.
349
350=cut
351
352
3531;
Note: See TracBrowser for help on using the repository browser.