3 # lilo-uuid-diskid - convert boot and root options to diskid
4 # and uuid in /etc/lilo.conf
6 # Copyright 2010-2014 Joachim Wiedorn <joodevel 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 = $liloconf . ".old";
46 our $liloconfnew = $liloconf . ".new";
47 our $fstabconf = "/etc/fstab";
48 our $idpath = "/dev/disk/by-id";
49 our $uuidpath = "/dev/disk/by-uuid";
50 our $labpath = "/dev/disk/by-label";
55 our $optboot = 0; # -1 = only ^#boot, 0 = nothing, 1 = ^boot exist
57 #-------------------- main program --------------------
64 $liloconf = "$ARGV[0]";
68 $liloconfold = $liloconf . ".old";
69 $liloconfnew = $liloconf . ".new";
70 $exit = convert_lilo_conf();
73 print "E: cannot open $liloconf: file not found!\n";
79 #-------------------- subroutines --------------------
81 sub convert_lilo_conf {
88 # at first read lilo.conf and search for 'boot'
90 open(MYFH, "<$liloconf") or die ("E: cannot open $liloconf: $!");
91 @sellines = grep(/^#?boot/, readline(MYFH));
94 # analyse the boot option in config file
95 foreach $line (@sellines) {
96 if ($line =~ /^boot/) {
97 # activated boot option found
103 # commented boot option found
104 if ($line =~ /^#boot/) { $optboot = -1; }
110 if($opt_v) { print "++++++++++ write options into $liloconf ++++++++++\n\n"; }
112 if ( detect_boot_device($bootline) == 0) {
113 # found diskid or uuid for boot device: $boot_id
118 if($opt_v) { print "E: cannot open $boot_id: link does not exist!\n"; }
123 if($opt_v) { print "\n"; }
127 print "E: cannot use $liloconf: uncomplete configuration!\n";
135 sub detect_boot_device {
137 my $boot_line = $_[0];
144 # the usual case: found ^boot in lilo.conf
145 $boot_disk = ($boot_line =~ /^boot *= *(\/dev\/.*)/) ? ($1) : ();
147 # check if the found partition is a raid volume
148 if($boot_disk =~ /\/dev\/md/) {
149 $boot_disk = check_raid($boot_disk);
152 elsif ($optboot == -1) {
153 # found only ^#boot in lilo.conf, then /etc/fstab is needed
156 print "W: no boot option in $liloconf: selecting from $fstabconf\n";
158 $boot_disk = read_fstab($fstabconf);
161 print "E: no boot option in $liloconf and no file $fstabconf found!\n";
167 if($boot_disk =~ /$idpath/
168 or $boot_disk =~ /$uuidpath/
169 or $boot_disk =~ /$labpath/) {
170 print "Boot option is already updated to $boot_disk\n";
171 $bootready = 1; $exit = 1;
174 if($opt_v) { print "Convert boot option $boot_disk into new ID\n"; }
176 # is it a block device name ?
179 $searchpath = ($_part eq $boot_disk) ? $idpath : $uuidpath;
181 $boot_id = $searchpath . "/" . find_id_link($boot_disk,$searchpath);
182 if(not -l "$boot_id") { $exit = 1; }
186 if($opt_v) { print "E: cannot read $boot_disk: link does not exist!\n"; }
199 $root_line = `awk '{ if (\$2=="/") print \$1}' <$ffile`;
201 # search for the last valid entry in /etc/fstab about root partition
202 foreach $_item (split("\n", $root_line)) {
203 if(not $_item =~ /#/) {
207 # check if the found partition is a raid volume
208 if($root_part =~ /\/dev\/md/) {
210 unless ($root_part =~ /^UUID/) {
211 # now find the right block device name
212 $root_part =~ s/\d+$//;
225 # check if the found partition is a raid volume
226 if($part =~ /\/dev\/md/)
229 $mdname =~ s/\/dev\///;
231 $md = `grep $mdname /proc/mdstat`;
233 @devices = split(" ", $md);
234 @devices = sort(@devices[4..$#devices]);
235 $part = "/dev/" . $devices[0];
242 sub detect_root_device {
244 my $root_line = $_[0];
250 # extract the root device name
251 $root_disk = ( $root_line =~ /^\t?root *= *(.*)/ ) ? ($1) : ();
254 # check if the found partition is a raid volume
255 if($root_disk =~ /\/dev\/md/) {
256 $root_disk = check_raid($root_disk);
260 # check if root device exist / also for raid volume
262 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; }
267 # nothing to do but perhaps give a message
269 $root_link = $root_disk;
270 $root_link =~ s{\"}{}g;
271 $root_link =~ s{^LABEL=}{/dev/disk/by-label/};
272 $root_link =~ s{^UUID=}{/dev/disk/by-uuid/};
273 if (not -l $root_link) {
274 if($opt_v) { print "W: cannot check $root_link: link does not exist!\n"; }
290 opendir(MYDH, "$path_id") or die("E: cannot open $path_id: $! \n");
291 @sellinks = grep(!/\-part\d\d?$/, grep(!/^\.\.?$/, readdir(MYDH)));
292 @sellinks = sort(@sellinks);
295 foreach $_idlink (@sellinks) {
296 if(not $_idlink =~ /^usb/ and length($_idlink) > 10 and $ok == 0) {
297 $_actlink = readlink("$path_id/$_idlink");
298 $_actlink =~ s/^\.\.\/\.\.\//\/dev\//;
299 if($opt_v) { print "** try: $_actlink => $_idlink \n"; }
301 if($_actlink eq $olddev) {
302 $newdevid = $_idlink;
303 if($opt_v) { print "** convert: $_actlink => $path_id/$_idlink \n"; }
310 if($opt_v and not $ok) { print "W: $olddev not converted: link not useful!\n\n"; }
315 sub write_boot_option {
325 # move old lilo.conf to lilo.conf_old
326 @status = stat($liloconf);
327 move ($liloconf, $liloconfold);
328 utime ($status[9],$status[9],$liloconfold);
329 chmod (0600,$liloconfold);
331 # copy all lines from lilo.conf_old into
332 # new lilo.conf and add 'boot=' line
334 open(MYFH_NEW, "> $liloconf") or die("E: cannot open $liloconf: $!");
335 open(MYFH_OLD, "< $liloconfold") or die ("E: cannot open $liloconfold: $!");
338 # line read from MYFH_OLD
341 if (/^boot/ and $ok == 0) {
342 $newline = "boot = $boot_id\n";
343 print MYFH_NEW "#" . $oldline;
344 print MYFH_NEW $newline;
345 if($opt_v) { print "+ #" . $oldline; }
346 print "+ " . $newline;
347 if($opt_v) { print "\n"; }
348 # convert only one time
351 elsif (/^#boot/ and $optboot == -1 and $ok == 0) {
352 # found a line with boot option commented out
353 $newline = "boot = $boot_id\n";
354 print MYFH_NEW $oldline;
355 print MYFH_NEW $newline;
356 if($opt_v) { print "+ " . $oldline; }
357 print "+ " . $newline;
358 if($opt_v) { print "\n"; }
359 # convert only one time
362 elsif (/^root/ or /^\troot/) {
363 # found a line with root option
364 if (detect_root_device($oldline) == 0) {
365 $comline = comment_root_line($oldline);
366 $newline = modern_root_line($oldline,$root_id);
367 print MYFH_NEW $comline;
368 print MYFH_NEW $newline;
369 if($opt_v) { print '+ ' . $comline; }
370 print '+ ' . $newline;
371 if($opt_v) { print "\n"; }
374 print MYFH_NEW $oldline;
378 print MYFH_NEW $oldline;
383 chmod (0600,$liloconf);
386 print "W: file $liloconf does not exist: nothing changed!\n";
390 sub comment_root_line {
392 my $rootline = $_[0];
394 if( $rootline =~ /root/) {
395 $rootline =~ s/root/#root/;
400 sub modern_root_line {
407 if($oldline =~ /root/) {
410 $indent =~ s/^(\t?)root.*/$1/;
411 $newline = $indent . "root = \"UUID=$rootid\"\n";
425 lilo-uuid-diskid - convert boot / root options to diskid and uuid in lilo.conf
429 B<lilo-uuid-diskid> [B<-h>] [B<-v>] [B<lilo.conf>]
433 This script looks for the boot block device or boot partition and create the
434 right diskid or uuid as boot option. Then it looks for all root partitions
435 and create the right uuids as root options.
437 These conversions are necessary for use with newer kernel (>= 2.6.26) if it
438 use the libata module for parallel and serial ATA interfaces of block devices
439 (i. e. hard disks with IDE or SATA interface, usbsticks).
451 Print verbose messages.
457 Lines in the configuration file /etc/lilo.conf:
460 boot = /dev/disk/by-id/ata-SAMSUNG_SV1604N_S01FJ10X999999
463 root = "UUID=18843936-00f9-4df0-a373-000d05a5dd44"
465 =head1 COPYRIGHT and LICENSE
467 Copyright (C) 2010-2014 Joachim Wiedorn
469 This script is free software; you can redistribute it and/or modify
470 it under the terms of the GNU General Public License as published by
471 the Free Software Foundation; either version 2 of the License, or
472 (at your option) any later version.
476 B<lilo-uuid-diskid> was written by Joachim Wiedorn.
478 This manual page was written by Joachim Wiedorn <joodevel at joonet.de>.
482 B<lilo>(8), B<update-lilo>(8), B<liloconfig>(8)