File Coverage

blib/lib/Linux/Bootloader/Detect.pm
Criterion Covered Total %
statement 37 49 75.5
branch 12 24 50.0
condition 4 11 36.3
subroutine 7 7 100.0
pod 4 4 100.0
total 64 95 67.3


line stmt bran cond sub pod time code
1             package Linux::Bootloader::Detect;
2              
3             =head1 NAME
4              
5             Linux::Bootloader::Detect - detects the bootloader and architecture of the system.
6              
7             =head1 SYNOPSIS
8              
9             Attempts to determine the bootloader by checking for configuration files
10             for grub, lilo, elilo and yaboot then searching the master boot record
11             for GRUB, LILO, ELILO and YABOOT.
12              
13             Determines the architecture by running uname -m.
14              
15             =head1 DESCRIPTION
16              
17             To attempt to discover the bootloader being used by the system
18             detect_bootloader first calls detect_bootloader_from_conf attempts to locate
19             /boot/grub/menu.lst, /etc/lilo.conf, /boot/efi/elilo.conf and
20             /etc/yaboot.conf and returns the corresponding bootloader name. If
21             either undef of multiple are returned because no configuration files or
22             multiple configuration files were found detect_bootloader calls
23             detect_bootloader_from_mbr which generates a list of all devices accessable from
24             the /dev directory reading in the first 512 bytes from each hd and sd
25             device using head then redirects the output to grep to determine if
26             "GRUB", "LILO", "ELILO" or "YABOOT" is present returning the
27             corresponding value if exactly one mbr on the system contained a
28             bootloader or multiple if more than one was found and undef if none were
29             found. detect_bootloader returns either grub, lilo, elilo, yaboot or
30             undef.
31              
32             To attempt to discover the architecture of the system
33             detect_architecture makes a uname -m system call returning x86, ppc,
34             ia64 or undef.
35              
36             =head1 FUNCTIONS
37              
38             =cut
39              
40 3     3   47716 use strict;
  3         6  
  3         121  
41 3     3   18 use warnings;
  3         4  
  3         104  
42              
43 3     3   26 use vars qw( $VERSION );
  3         5  
  3         1996  
44             our $VERSION = '1.2';
45              
46             =head3 detect_architecture([style])
47              
48             Input:
49             Output: string
50              
51             This function determines the architecture by calling uname -m. By
52             default it will report back exactly what uname -m reports, but if you
53             specify a "style", detect_architecture will do some mappings. Possible
54             styles include:
55              
56             Style Example return values (not an exhaustive list...)
57             [none] i386, i686, sparc, sun4u, ppc64, s390x, x86_64, parisc64
58             linux i386, i386, sparc, sparc, ppc64, s390, x86_64, parisc
59             gentoo x86, x86, sparc, sparc, ppc64, amd64, hppa
60              
61             Returns undef on error.
62              
63             =cut
64              
65             sub detect_architecture {
66 4   100 4 1 59 my $arch_style = shift || 'uname';
67              
68 4         10 my $arch;
69 4 100       31 if ($arch_style eq 'linux') {
    100          
70 1         9256 $arch = `uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/ -e s/s390x/s390/ -e s/parisc64/parisc/`;
71 1         27 chomp $arch;
72             } elsif ($arch_style eq 'gentoo') {
73 1         32711 $arch = `uname -m | sed -e s/i.86/x86/ -e s/sun4u/sparc/ -e s/arm.*/arm/ -e s/sa110/arm/ -e s/x86_64/amd64/ -e s/sparc.*/sparc/ -e s/parisc.*/hppa/`;
74 1         25 chomp $arch;
75             } else {
76 2         57519 $arch = `uname -m`;
77 2         43 chomp $arch;
78             }
79 4         228 return $arch;
80             }
81              
82             =head3 detect_bootloader(['device1', 'device2', ...])
83              
84             Input: devices to detect against (optional)
85             Output: string
86              
87             This function attempts to determine the bootloader being used on the
88             system by first checking for conf files and then falling back to check
89             the master boot record.
90              
91             Possible return values:
92              
93             grub grub was determined to be the bootloader in use
94             lilo lilo was determined to be is the bootloader in use
95             elilo elilo was determined to be the bootloader in use
96             yaboot yaboot was determined to be the bootloader in use
97             undef it was impossible to determine which bootloader was being used
98             due either to configuration files for multiple bootloaders or
99             bootloader on multiple hard disks
100              
101             =cut
102              
103             sub detect_bootloader {
104 1   33 1 1 7 return detect_bootloader_from_conf(@_)
105             || detect_bootloader_from_mbr(@_);
106             }
107              
108             =head2 detect_bootloader_from_conf()
109              
110             Detects bootloaders by the presence of config files. This is not as
111             reliable of a mechanism as looking in the MBR, but tends to be
112             significantly faster.
113              
114             If called in list context, it will return a list of the bootloaders that
115             it found.
116              
117             If called in scalar context and only a single bootloader config file is
118             present it will return the name of that bootloader. Otherwise, if
119             multiple (or no) bootloaders are detected, it will return undef.
120              
121             =cut
122              
123             sub detect_bootloader_from_conf {
124 2     2 1 9 my @boot_loader = ();
125              
126 2         170 my %boot_list = ( grub => '/boot/grub/menu.lst',
127             lilo => '/etc/lilo.conf',
128             elilo => '/etc/elilo.conf',
129             yaboot => '/etc/yaboot.conf'
130             );
131              
132 2         14 foreach my $key ( sort keys %boot_list ) {
133 8 50       370 if ( -f $boot_list{$key} ) {
134 0         0 push ( @boot_loader, $key );
135             }
136             }
137              
138 2 100       15 if (wantarray()) {
    50          
139 1         9 return @boot_loader;
140             } elsif (@boot_loader == 1) {
141 0         0 return pop( @boot_loader );
142             } else {
143 1         12 return undef;
144             }
145             }
146              
147             =head2 detect_bootloader_from_mbr([@devices])
148              
149             Detects the bootloader by scanning the master boot record (MBR) of the
150             specified devices (or all devices if not indicated).
151              
152             The device arguments must be relative to the /dev/ directory. I.e.,
153             ('hda', 'sdb', 'cdroms/cdrom0', etc.)
154              
155             =cut
156              
157             sub detect_bootloader_from_mbr {
158 2     2 1 2366 my @filelist = @_;
159 2         19 my @boot_loader = ();
160              
161 2         35 my %map = (
162             "GRUB" => 'grub',
163             "LILO" => 'lilo',
164             "EFI" => 'elilo',
165             "yaboot" => 'yaboot',
166             );
167              
168 2 50 33     133 if ( ! @filelist && opendir( DIRH, "/sys/block" ) ) {
169 2         65 @filelist = grep { /^[sh]d.$/ } readdir(DIRH);
  60         357  
170 2         38 closedir(DIRH);
171             }
172              
173 2         8 foreach ( @filelist ) {
174 0 0       0 if ( -b "/dev/$_" ) {
175 0         0 my $strings = `dd if=/dev/$_ bs=512 count=1 2>/dev/null | strings`;
176 0         0 foreach my $loader (keys %map) {
177 0 0       0 if ($strings =~ /$loader/ms) {
178 0         0 push @boot_loader, $map{$loader};
179             }
180             }
181             }
182             }
183            
184 2 50       22 if (wantarray()) {
    50          
    50          
185             # Show them all
186 0         0 return @boot_loader;
187             } elsif (@boot_loader == 1) {
188             # Found exactly one
189 0         0 return pop @boot_loader;
190             } elsif (@boot_loader == 2) {
191             # This is the Lilo/Grub exception
192             # Grub on MBR with previous Lilo install
193             # Are they lilo and grub in that order?
194 0 0 0     0 if ($boot_loader[0] eq 'lilo' and $boot_loader[1] eq 'grub'){
195 0         0 warn "Warning: Grub appears to be used currently, but Lilo was in pasti.\n";
196 0         0 return $boot_loader[1];
197             }
198             }
199              
200             # Either none or too many to choose from
201 2         21 return undef;
202             }
203              
204             1;
205              
206             =head1 AUTHOR
207              
208             Open Source Development Labs, Engineering Department
209              
210             =head1 COPYRIGHT
211              
212             Copyright (C) 2006 Open Source Development Labs
213             All Rights Reserved.
214              
215             This script is free software; you can redistribute it and/or modify it
216             under the same terms as Perl itself.
217              
218             =head1 SEE ALSO
219              
220             L
221              
222             =cut
223