3 # lilo-uuid-diskid - convert boot and root options to diskid
4 # and uuid in /etc/lilo.conf
6 # Copyright 2010-2011 Joachim Wiedorn <ad_debian at joonet.de>
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software
20 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
31 #---- global variables
40 # define perldoc usage
41 pod2usage(1) if $opt_h;
44 our $liloconf = "/etc/lilo.conf";
45 our $liloconfold = '';
46 our $fstabconf = "/etc/fstab";
47 our $idpath = "/dev/disk/by-id";
48 our $uuidpath = "/dev/disk/by-uuid";
49 our $labpath = "/dev/disk/by-label";
54 our $optboot = 0; # -1 = only ^#boot, 0 = nothing, 1 = ^boot exist
56 #-------------------- main program --------------------
63 $liloconf = "$ARGV[0]";
67 $liloconfold = $liloconf . "_old";
68 $exit = convert_lilo_conf();
71 print "cannot open $liloconf: file not found!\n";
77 #-------------------- subroutines --------------------
79 sub convert_lilo_conf {
86 # at first read lilo.conf and search for 'boot'
88 open(MYFH, "<$liloconf") or die ("cannot open $liloconf: $!");
89 @sellines = grep(/^#?boot/, readline(MYFH));
92 # analyse the boot option in config file
93 foreach $line (@sellines) {
94 if ($line =~ /^boot/) {
95 # activated boot option found
101 # commented boot option found
102 if ($line =~ /^#boot/) { $optboot = -1; }
108 if($opt_v) { print "++++++++++ write options into $liloconf ++++++++++\n\n"; }
110 if ( detect_boot_device($bootline) == 0) {
111 # found diskid or uuid for boot device: $boot_id
116 if($opt_v) { print "cannot open $boot_id: link does not exist!\n"; }
121 if($opt_v) { print "\n"; }
125 print "cannot use $liloconf: uncomplete configuration!\n";
133 sub detect_boot_device {
135 my $boot_line = $_[0];
142 # the usual case: found ^boot in lilo.conf
143 $boot_disk = ($boot_line =~ /^boot *= *(\/dev\/.*)/) ? ($1) : ();
145 # check if the found partition is a raid volume
146 if($boot_disk =~ /\/dev\/md/) {
147 $boot_disk = check_raid($boot_disk);
150 elsif ($optboot == -1) {
151 # found only ^#boot in lilo.conf, then /etc/fstab is needed
154 print "no boot option in $liloconf: selecting from $fstabconf\n";
156 $boot_disk = read_fstab($fstabconf);
159 print "no boot option in $liloconf and no file $fstabconf found!\n";
165 if($boot_disk =~ /$idpath/
166 or $boot_disk =~ /$uuidpath/
167 or $boot_disk =~ /$labpath/) {
168 print "boot option is already updated to $boot_disk\n";
169 $bootready = 1; $exit = 1;
172 if($opt_v) { print "convert boot option $boot_disk into new ID\n"; }
174 # is it a block device name ?
177 $searchpath = ($_part eq $boot_disk) ? $idpath : $uuidpath;
179 $boot_id = $searchpath . "/" . find_id_link($boot_disk,$searchpath);
180 if(not -l "$boot_id") { $exit = 1; }
184 if($opt_v) { print "cannot read $boot_disk: link does not exist!\n"; }
197 $root_line = `awk '{ if (\$2=="/") print \$1}' <$ffile`;
199 # search for the last valid entry in /etc/fstab about root partition
200 foreach $_item (split("\n", $root_line)) {
201 if(not $_item =~ /#/) {
205 # check if the found partition is a raid volume
206 if($root_part =~ /\/dev\/md/) {
207 $root_part = check_raid($root_part);
209 unless ($root_part =~ /^UUID/) {
210 # now find the right block device name
211 $root_part =~ s/\d+$//;
212 $root_part =~ s/part$/disc/;
222 # check if the found partition is a raid volume
223 if($part =~ /\/dev\/md/)
230 $mdname =~ s/\/dev\///;
232 $md = `grep $mdname /proc/mdstat`;
234 @devices = split(" ", $md);
235 @devices = sort(@devices[4..$#devices]);
236 $part = "/dev/" . $devices[0];
243 sub detect_root_device {
245 my $root_line = $_[0];
251 # extract the root device name
252 $root_disk = ( $root_line =~ /^\t?root *= *(.*)/ ) ? ($1) : ();
255 # check if the found partition is a raid volume
256 if($root_disk =~ /\/dev\/md/) {
257 $root_disk = check_raid($root_disk);
261 # check if root device exist
263 if($opt_v) { print "convert root option $root_disk into new UUID\n"; }
264 $root_id = find_id_link($root_disk,$uuidpath);
265 if (not -l "$uuidpath/$root_id") { $exit = 1; }
268 # nothing to do but perhaps give a message
270 $root_link = $root_disk;
271 $root_link =~ s{\"}{}g;
272 $root_link =~ s{^LABEL=}{/dev/disk/by-label/};
273 $root_link =~ s{^UUID=}{/dev/disk/by-uuid/};
274 if (not -b $root_link) {
275 if($opt_v) { print "cannot check $root_disk: link does not exist!\n"; }
291 opendir(MYDH, "$path_id") or die("cannot open $path_id: $! \n");
292 @sellinks = grep(!/\-part\d\d?$/, grep(!/^\.\.?$/, readdir(MYDH)));
293 @sellinks = sort(@sellinks);
296 foreach $_idlink (@sellinks) {
297 if(not $_idlink =~ /^usb/ and length($_idlink) > 10 and $ok == 0) {
298 $_actlink = readlink("$path_id/$_idlink");
299 $_actlink =~ s/^\.\.\/\.\.\//\/dev\//;
300 if($opt_v) { print "** try: $_actlink => $_idlink \n"; }
302 if($_actlink eq $olddev) {
303 $newdevid = $_idlink;
304 if($opt_v) { print "** convert: $_actlink => $path_id/$_idlink \n"; }
311 if($opt_v and not $ok) { print "$olddev not converted: link not useful\n\n"; }
316 sub write_boot_option {
326 # move old lilo.conf to lilo.conf_old
327 @status = stat($liloconf);
328 move ($liloconf, $liloconfold);
329 utime ($status[9],$status[9],$liloconfold);
330 chmod (0600,$liloconfold);
332 # copy all lines from lilo.conf_old into
333 # new lilo.conf and add 'boot=' line
335 open(MYFH_NEW, "> $liloconf") or die("cannot open $liloconf: $!");
336 open(MYFH_OLD, "< $liloconfold") or die ("cannot open $liloconfold: $!");
339 # line read from MYFH_OLD
342 if (/^boot/ and $ok == 0) {
343 $newline = "boot = $boot_id\n";
344 print MYFH_NEW "#" . $oldline;
345 print MYFH_NEW $newline;
346 if($opt_v) { print "+ #" . $oldline; }
347 print "+ " . $newline;
348 if($opt_v) { print "\n"; }
349 # convert only one time
352 elsif (/^#boot/ and $optboot == -1 and $ok == 0) {
353 # found a line with boot option commented out
354 $newline = "boot = $boot_id\n";
355 print MYFH_NEW $oldline;
356 print MYFH_NEW $newline;
357 if($opt_v) { print "+ " . $oldline; }
358 print "+ " . $newline;
359 if($opt_v) { print "\n"; }
360 # convert only one time
363 elsif (/^root/ or /^\troot/) {
364 # found a line with root option
365 if (detect_root_device($oldline) == 0) {
366 $comline = comment_root_line($oldline);
367 $newline = modern_root_line($oldline,$root_id);
368 print MYFH_NEW $comline;
369 print MYFH_NEW $newline;
370 if($opt_v) { print '+ ' . $comline; }
371 print '+ ' . $newline;
372 if($opt_v) { print "\n"; }
375 print MYFH_NEW $oldline;
379 print MYFH_NEW $oldline;
384 chmod (0600,$liloconf);
387 print "file $liloconf does not exist: nothing changed\n";
391 sub comment_root_line {
393 my $rootline = $_[0];
395 if( $rootline =~ /root/) {
396 $rootline =~ s/root/#root/;
401 sub modern_root_line {
408 if($oldline =~ /root/) {
411 $indent =~ s/^(\t?)root.*/$1/;
412 $newline = $indent . "root = \"UUID=$rootid\"\n";
426 lilo-uuid-diskid - convert boot / root options to diskid and uuid in lilo.conf
430 lilo-uuid-diskid [-h] [-v] [lilo.conf]
434 This script looks for the boot block device or boot partition and create the
435 right diskid or uuid as boot option. Then it looks for all root partitions
436 and create the right uuids as root options.
438 These conversions are necessary for use with newer kernel (>= 2.6.26) if it
439 use the libata module for parallel and serial ATA interfaces of block devices
440 (i. e. hard disks with IDE or SATA interface, usbsticks).
444 Lines in the configuration file /etc/lilo.conf:
447 boot = /dev/disk/by-id/ata-SAMSUNG_SV1604N_S01FJ10X999999
450 root = "UUID=/dev/disk/by-uuid/18843936-00f9-4df0-a373-000d05a5dd44"
462 Print verbose messages.
468 B<lilo-uuid-diskid> was written by Joachim Wiedorn.