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/) {
208 unless ($root_part =~ /^UUID/) {
209 # now find the right block device name
210 $root_part =~ s/\d+$//;
223 # check if the found partition is a raid volume
224 if($part =~ /\/dev\/md/)
227 $mdname =~ s/\/dev\///;
229 $md = `grep $mdname /proc/mdstat`;
231 @devices = split(" ", $md);
232 @devices = sort(@devices[4..$#devices]);
233 $part = "/dev/" . $devices[0];
240 sub detect_root_device {
242 my $root_line = $_[0];
248 # extract the root device name
249 $root_disk = ( $root_line =~ /^\t?root *= *(.*)/ ) ? ($1) : ();
252 # check if the found partition is a raid volume
253 if($root_disk =~ /\/dev\/md/) {
254 $root_disk = check_raid($root_disk);
258 # check if root device exist / also for raid volume
260 if($opt_v) { print "convert root option $root_disk into new UUID\n"; }
261 $root_id = find_id_link($root_disk,$uuidpath);
262 if (not -l "$uuidpath/$root_id") { $exit = 1; }
265 # nothing to do but perhaps give a message
267 $root_link = $root_disk;
268 $root_link =~ s{\"}{}g;
269 $root_link =~ s{^LABEL=}{/dev/disk/by-label/};
270 $root_link =~ s{^UUID=}{/dev/disk/by-uuid/};
271 if (not -l $root_link) {
272 if($opt_v) { print "cannot check $root_link: link does not exist!\n"; }
288 opendir(MYDH, "$path_id") or die("cannot open $path_id: $! \n");
289 @sellinks = grep(!/\-part\d\d?$/, grep(!/^\.\.?$/, readdir(MYDH)));
290 @sellinks = sort(@sellinks);
293 foreach $_idlink (@sellinks) {
294 if(not $_idlink =~ /^usb/ and length($_idlink) > 10 and $ok == 0) {
295 $_actlink = readlink("$path_id/$_idlink");
296 $_actlink =~ s/^\.\.\/\.\.\//\/dev\//;
297 if($opt_v) { print "** try: $_actlink => $_idlink \n"; }
299 if($_actlink eq $olddev) {
300 $newdevid = $_idlink;
301 if($opt_v) { print "** convert: $_actlink => $path_id/$_idlink \n"; }
308 if($opt_v and not $ok) { print "$olddev not converted: link not useful\n\n"; }
313 sub write_boot_option {
323 # move old lilo.conf to lilo.conf_old
324 @status = stat($liloconf);
325 move ($liloconf, $liloconfold);
326 utime ($status[9],$status[9],$liloconfold);
327 chmod (0600,$liloconfold);
329 # copy all lines from lilo.conf_old into
330 # new lilo.conf and add 'boot=' line
332 open(MYFH_NEW, "> $liloconf") or die("cannot open $liloconf: $!");
333 open(MYFH_OLD, "< $liloconfold") or die ("cannot open $liloconfold: $!");
336 # line read from MYFH_OLD
339 if (/^boot/ and $ok == 0) {
340 $newline = "boot = $boot_id\n";
341 print MYFH_NEW "#" . $oldline;
342 print MYFH_NEW $newline;
343 if($opt_v) { print "+ #" . $oldline; }
344 print "+ " . $newline;
345 if($opt_v) { print "\n"; }
346 # convert only one time
349 elsif (/^#boot/ and $optboot == -1 and $ok == 0) {
350 # found a line with boot option commented out
351 $newline = "boot = $boot_id\n";
352 print MYFH_NEW $oldline;
353 print MYFH_NEW $newline;
354 if($opt_v) { print "+ " . $oldline; }
355 print "+ " . $newline;
356 if($opt_v) { print "\n"; }
357 # convert only one time
360 elsif (/^root/ or /^\troot/) {
361 # found a line with root option
362 if (detect_root_device($oldline) == 0) {
363 $comline = comment_root_line($oldline);
364 $newline = modern_root_line($oldline,$root_id);
365 print MYFH_NEW $comline;
366 print MYFH_NEW $newline;
367 if($opt_v) { print '+ ' . $comline; }
368 print '+ ' . $newline;
369 if($opt_v) { print "\n"; }
372 print MYFH_NEW $oldline;
376 print MYFH_NEW $oldline;
381 chmod (0600,$liloconf);
384 print "file $liloconf does not exist: nothing changed\n";
388 sub comment_root_line {
390 my $rootline = $_[0];
392 if( $rootline =~ /root/) {
393 $rootline =~ s/root/#root/;
398 sub modern_root_line {
405 if($oldline =~ /root/) {
408 $indent =~ s/^(\t?)root.*/$1/;
409 $newline = $indent . "root = \"UUID=$rootid\"\n";
423 lilo-uuid-diskid - convert boot / root options to diskid and uuid in lilo.conf
427 lilo-uuid-diskid [-h] [-v] [lilo.conf]
431 This script looks for the boot block device or boot partition and create the
432 right diskid or uuid as boot option. Then it looks for all root partitions
433 and create the right uuids as root options.
435 These conversions are necessary for use with newer kernel (>= 2.6.26) if it
436 use the libata module for parallel and serial ATA interfaces of block devices
437 (i. e. hard disks with IDE or SATA interface, usbsticks).
441 Lines in the configuration file /etc/lilo.conf:
444 boot = /dev/disk/by-id/ata-SAMSUNG_SV1604N_S01FJ10X999999
447 root = "UUID=18843936-00f9-4df0-a373-000d05a5dd44"
459 Print verbose messages.
465 B<lilo-uuid-diskid> was written by Joachim Wiedorn.