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 # now find the right block device name
210 $root_part =~ s/\d+$//;
211 $root_part =~ s/part$/disc/;
220 # check if the found partition is a raid volume
221 if($part =~ /\/dev\/md/)
228 $mdname =~ s/\/dev\///;
230 $md = `grep $mdname /proc/mdstat`;
232 @devices = split(" ", $md);
233 @devices = sort(@devices[4..$#devices]);
234 $part = "/dev/" . $devices[0];
241 sub detect_root_device {
243 my $root_line = $_[0];
249 # extract the root device name
250 $root_disk = ( $root_line =~ /^\t?root *= *(.*)/ ) ? ($1) : ();
253 # check if the found partition is a raid volume
254 if($root_disk =~ /\/dev\/md/) {
255 $root_disk = check_raid($root_disk);
259 # check if root device exist
261 if($opt_v) { print "convert root option $root_disk into new UUID\n"; }
262 $root_id = find_id_link($root_disk,$uuidpath);
263 if (not -l "$uuidpath/$root_id") { $exit = 1; }
266 # nothing to do but perhaps give a message
268 $root_link = $root_disk;
269 $root_link =~ s{\"}{}g;
270 $root_link =~ s{^LABEL=}{/dev/disk/by-label/};
271 $root_link =~ s{^UUID=}{/dev/disk/by-uuid/};
272 if (not -b $root_link) {
273 if($opt_v) { print "cannot check $root_disk: link does not exist!\n"; }
289 opendir(MYDH, "$path_id") or die("cannot open $path_id: $! \n");
290 @sellinks = grep(!/\-part\d\d?$/, grep(!/^\.\.?$/, readdir(MYDH)));
291 @sellinks = sort(@sellinks);
294 foreach $_idlink (@sellinks) {
295 if(not $_idlink =~ /^usb/ and length($_idlink) > 10 and $ok == 0) {
296 $_actlink = readlink("$path_id/$_idlink");
297 $_actlink =~ s/^\.\.\/\.\.\//\/dev\//;
298 if($opt_v) { print "** try: $_actlink => $_idlink \n"; }
300 if($_actlink eq $olddev) {
301 $newdevid = $_idlink;
302 if($opt_v) { print "** convert: $_actlink => $path_id/$_idlink \n"; }
309 if($opt_v and not $ok) { print "$olddev not converted: link not useful\n\n"; }
314 sub write_boot_option {
324 # move old lilo.conf to lilo.conf_old
325 @status = stat($liloconf);
326 move ($liloconf, $liloconfold);
327 utime ($status[9],$status[9],$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;
383 print "file $liloconf does not exist: nothing changed\n";
387 sub comment_root_line {
389 my $rootline = $_[0];
391 if( $rootline =~ /root/) {
392 $rootline =~ s/root/#root/;
397 sub modern_root_line {
404 if($oldline =~ /root/) {
407 $indent =~ s/^(\t?)root.*/$1/;
408 $newline = $indent . "root = \"UUID=$rootid\"\n";
422 lilo-uuid-diskid - convert boot / root options to diskid and uuid in lilo.conf
426 lilo-uuid-diskid [-h] [-v] [lilo.conf]
430 This script looks for the boot block device or boot partition and create the
431 right diskid or uuid as boot option. Then it looks for all root partitions
432 and create the right uuids as root options.
434 These conversions are necessary for use with newer kernel (>= 2.6.26) if it
435 use the libata module for parallel and serial ATA interfaces of block devices
436 (i. e. hard disks with IDE or SATA interface, usbsticks).
440 Lines in the configuration file /etc/lilo.conf:
443 boot = /dev/disk/by-id/ata-SAMSUNG_SV1604N_S01FJ10X999999
446 root = "UUID=/dev/disk/by-uuid/18843936-00f9-4df0-a373-000d05a5dd44"
458 Print verbose messages.
464 B<lilo-uuid-diskid> was written by Joachim Wiedorn.