3 # lilo-uuid-diskid - convert boot / root options to diskid and
6 # Copyright 2010 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,
30 #---- global variables
39 # define perldoc usage
40 pod2usage(1) if $opt_h;
43 our $liloconf = "/etc/lilo.conf";
44 our $liloconfold = '';
45 our $fstabconf = "/etc/fstab";
46 our $idpath = "/dev/disk/by-id";
47 our $uuidpath = "/dev/disk/by-uuid";
52 our $optboot = 0; # -1 = only ^#boot, 0 = nothing, 1 = ^boot exist
54 #-------------------- main program --------------------
61 $liloconf = "$ARGV[0]";
65 $liloconfold = $liloconf . "_old";
66 $exit = convert_lilo_conf();
69 print "cannot open $liloconf: file not found!\n";
75 #-------------------- subroutines --------------------
77 sub convert_lilo_conf {
84 # at first read lilo.conf and search for 'boot'
86 open(MYFH, "<$liloconf") or die ("cannot open $liloconf: $!");
87 @sellines = grep(/^#?boot/, readline(MYFH));
90 # analyse the boot option in config file
91 foreach $line (@sellines) {
92 if ($line =~ /^boot/) {
93 # activated boot option found
99 # commented boot option found
100 if ($line =~ /^#boot/) { $optboot = -1; }
106 if($opt_v) { print "++++++++++ write options into $liloconf ++++++++++\n\n"; }
108 if ( detect_boot_device($bootline) == 0) {
109 # found diskid or uuid for boot device: $boot_id
114 if($opt_v) { print "cannot open $boot_id: link does not exist!\n"; }
119 if($opt_v) { print "\n"; }
123 print "cannot use $liloconf: uncomplete configuration!\n";
131 sub detect_boot_device {
133 my $boot_line = $_[0];
140 # the usual case: found ^boot in lilo.conf
141 $boot_disk = ($boot_line =~ /^boot *= *(\/dev\/.*)/) ? ($1) : ();
143 # check if the found partition is a raid volume
144 if($boot_disk =~ /\/dev\/md/) {
145 $boot_disk = check_raid($boot_disk);
148 elsif ($optboot == -1) {
149 # found only ^#boot in lilo.conf, then /etc/fstab is needed
152 print "no boot option in $liloconf: selecting from $fstabconf\n";
154 $boot_disk = read_fstab($fstabconf);
157 print "no boot option in $liloconf and no file $fstabconf found!\n";
163 if($boot_disk =~ /$idpath/ or $boot_disk =~ /$uuidpath/) {
164 print "boot option is already updated to $boot_disk\n";
165 $bootready = 1; $exit = 1;
168 if($opt_v) { print "convert boot option $boot_disk into new ID\n"; }
170 # is it a block device name ?
173 $searchpath = ($_part eq $boot_disk) ? $idpath : $uuidpath;
175 $boot_id = $searchpath . "/" . find_id_link($boot_disk,$searchpath);
176 if(not -l "$boot_id") { $exit = 1; }
180 if($opt_v) { print "cannot read $boot_disk: link does not exist!\n"; }
194 $root_line = `awk '{ if (\$2=="/") print \$1}' <$ffile`;
196 # search for the last valid entry in /etc/fstab about root partition
197 foreach $_item (split("\n", $root_line)) {
198 if(not $_item =~ /#/) {
202 # check if the found partition is a raid volume
203 if($root_part =~ /\/dev\/md/) {
204 $root_part = check_raid($root_part);
206 # now find the right block device name
207 $root_part =~ s/\d+$//;
208 $root_part =~ s/part$/disc/;
217 # check if the found partition is a raid volume
218 if($part =~ /\/dev\/md/)
225 $mdname =~ s/\/dev\///;
227 $md = `grep $mdname /proc/mdstat`;
229 @devices = split(" ", $md);
230 @devices = sort(@devices[4..$#devices]);
231 $part = "/dev/" . $devices[0];
238 sub detect_root_device {
240 my $root_line = $_[0];
245 # extract the root device name
246 $root_disk = ($root_line =~ /^\t?root *= *(\/dev\/.*)/) ? ($1) : ();
249 # check if the found partition is a raid volume
250 if($root_disk =~ /\/dev\/md/) {
251 $root_disk = check_raid($root_disk);
257 if($root_disk =~ /$uuidpath/) {
258 print "$root_disk is already updated - nothing to do\n";
261 if($opt_v) { print "convert root option $root_disk into new UUID\n"; }
263 $root_id = find_id_link($root_disk,$uuidpath);
264 if (not -l "$uuidpath/$root_id") { $exit = 1; }
268 if($opt_v) { print "cannot read $root_disk: link does not exist!\n"; }
284 opendir(MYDH, "$path_id") or die("cannot open $path_id: $! \n");
286 @sellinks = grep(!/\-part\d\d?$/, grep(!/^\.\.?$/, readdir(MYDH)));
287 foreach $_idlink (@sellinks) {
289 if(not $_idlink =~ /^usb/ and not $_idlink =~ /^scsi/
290 and length($_idlink) > 10 and $ok == 0) {
292 $_actlink = readlink("$path_id/$_idlink");
293 $_actlink =~ s/^\.\.\/\.\.\//\/dev\//;
294 if($opt_v) { print "** try: $_actlink => $_idlink \n"; }
296 if($_actlink eq $olddev) {
297 $newdevid = $_idlink;
298 if($opt_v) { print "** convert: $_actlink => $path_id/$_idlink \n"; }
306 if($opt_v and not $ok) { print "$olddev not converted: link not useful\n\n"; }
311 sub write_boot_option {
321 # move old lilo.conf to lilo.conf_old
322 @status = stat($liloconf);
323 move ($liloconf, $liloconfold);
324 utime ($status[9],$status[9],$liloconfold);
326 # copy all lines from lilo.conf_old into
327 # new lilo.conf and add 'boot=' line
329 open(MYFH_NEW, "> $liloconf") or die("cannot open $liloconf: $!");
330 open(MYFH_OLD, "< $liloconfold") or die ("cannot open $liloconfold: $!");
333 # line read from MYFH_OLD
336 if (/^boot/ and $ok == 0) {
337 $newline = "boot = $boot_id\n";
338 print MYFH_NEW "#" . $oldline;
339 print MYFH_NEW $newline;
340 if($opt_v) { print "+ #" . $oldline; }
341 print "+ " . $newline;
342 if($opt_v) { print "\n"; }
343 # convert only one time
346 elsif (/^#boot/ and $optboot == -1 and $ok == 0) {
347 # found a line with boot option commented out
348 $newline = "boot = $boot_id\n";
349 print MYFH_NEW $oldline;
350 print MYFH_NEW $newline;
351 if($opt_v) { print "+ " . $oldline; }
352 print "+ " . $newline;
353 if($opt_v) { print "\n"; }
354 # convert only one time
357 elsif (/^root/ or /^\troot/) {
358 # found a line with root option
359 if (detect_root_device($oldline) == 0) {
360 $comline = comment_root_line($oldline);
361 $newline = modern_root_line($oldline,$root_id);
362 print MYFH_NEW $comline;
363 print MYFH_NEW $newline;
364 if($opt_v) { print '+ ' . $comline; }
365 print '+ ' . $newline;
366 if($opt_v) { print "\n"; }
369 print MYFH_NEW $oldline;
373 print MYFH_NEW $oldline;
380 print "file $liloconf does not exist: nothing changed\n";
384 sub comment_root_line {
386 my $rootline = $_[0];
388 if( $rootline =~ /root/) {
389 $rootline =~ s/root/#root/;
394 sub modern_root_line {
401 if($oldline =~ /root/) {
404 $indent =~ s/^(\t?)root.*/$1/;
405 $newline = $indent . "root = \"UUID=$rootid\"\n";
419 lilo-uuid-diskid - convert boot / root options to diskid and uuid in lilo.conf
423 lilo-uuid-diskid [-h] [-v] [lilo.conf]
427 This script looks for the boot block device or boot partition and create the
428 right diskid or uuid as boot option. Then it looks for all root partitions
429 and create the right uuids as root options.
431 These conversions are necessary for use with newer kernel (>= 2.6.26) if it
432 use the libata module for parallel and serial ATA interfaces of block devices
433 (i. e. hard disks with IDE or SATA interface, usbsticks).
437 Lines in the configuration file /etc/lilo.conf:
440 boot = /dev/disk/by-id/ata-SAMSUNG_SV1604N_S01FJ10X999999
443 root = "UUID=/dev/disk/by-uuid/18843936-00f9-4df0-a373-000d05a5dd44"
455 Print verbose messages.
461 B<lilo-uuid-diskid> was written by Joachim Wiedorn.