3 # liloconfig - creating a new lilo.conf file
5 # Copyright 2011 Joachim Wiedorn <ad_debian@joonet.de>
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
30 #---- global variables
36 # h: help, v: verbose, f: force
41 # define perldoc usage
42 pod2usage(1) if $opt_h;
45 our $liloconf = "/etc/lilo.conf";
46 our $conftmp_1 = "/tmp/lilotmp1";
47 our $conftmp_2 = "/tmp/lilotmp2";
48 our $liloconfold = $liloconf . ".old";
49 our $liloconfnew = $liloconf . ".new";
50 our $fstabconf = "/etc/fstab";
52 our $idpath = "/dev/disk/by-id";
53 our $uuidpath = "/dev/disk/by-uuid";
54 our $lblpath = "/dev/disk/by-label";
55 our $template = "/usr/share/doc/lilo/examples/lilo.example.conf.gz";
57 our $rootpart; # found root part
58 our $root_dev; # /dev/hdX9, /dev/sdX9, /dev/md/*
59 our $root_id; # UUID, LABEL, ID
60 our $boot_dev; # /dev/hdX, /dev/sdX, /dev/md
61 our $boot_id; # DISK-ID
63 #-------------------- main program --------------------
70 $liloconf = "$ARGV[0]";
71 $liloconfold = $liloconf . ".old";
72 $liloconfnew = $liloconf . ".new";
74 if (-f $liloconf and not $opt_f) {
75 print "$prog: $liloconf already exist! Please use '-f' for overwriting.\n";
79 $exit = create_lilo_conf()
84 #-------------------- subroutines --------------------
86 sub create_lilo_conf {
91 # search for root device in fstab and convert it
92 $found = detect_root_device();
94 # convert root device to boot device
95 if ($found) { $found = convert_boot_device(); }
97 # finally write new lilo.conf file
98 if ($found) { $exit = write_lilo_conf(); }
103 sub detect_root_device {
105 # read fstab and find root device;
106 my $found = read_fstab();
108 # identify root device: root_dev and root_id
109 if ($found) { $found = convert_root_device(); }
118 my $broken_fstab = 1;
122 # check fstab for root device
124 # Parsing fstab for the root partition
125 open(FSTAB, "<$fstabconf") or die "$prog: couldn't open $fstabconf: $!\n";
128 # Search magic string which indicates a base filesystem
129 $base_fstab = 1 if /^# UNCONFIGURED FSTAB FOR BASE SYSTEM/;
130 next if /^#/; # ignore comment lines
132 s/^[ \t]+//; # remove space or tab at begin of the line
133 ($root_part,$mountpoint) = split(/[ \t]+/);
134 next unless defined $mountpoint; # ignore empty lines too
136 # stop if we found the root device...
137 if ($mountpoint eq '/') {
142 close(FSTAB) or die "$prog: couldn't close $fstabconf: $!\n";
146 print "E: It seems you want configure the base filesystem \n" .
147 "and I'm therefore simply going to exit successfully \n" .
148 "without trying to actually configure LILO properly. \n";
152 print "E: It seems the file /etc/fstab is not properly \n" .
153 "configured: no root partition '/' found! \n";
156 # save the found root device
157 $rootpart = $root_part;
162 sub convert_root_device {
167 # global variables: $root_dev, $root_id
169 if ($rootpart =~ /\/dev\//) {
170 $root_disk = $rootpart;
173 $root_dev = $root_disk;
174 if($opt_v) { print "Convert root option $root_disk into UUID\n"; }
175 $root_id = find_id_link($root_disk,$uuidpath);
177 if (not -l "$uuidpath/$root_id") {
178 if($opt_v) { print "W: could not find UUID for $root_disk!\n"; }
179 ## than we want use root_dev in lilo.conf
183 # finally add uuid label
184 $root_id = "UUID=" . $root_id;
188 if($opt_v) { print "E: cannot check $root_disk: device does not exist!\n"; }
192 elsif ($rootpart =~ /^UUID/ or $rootpart =~ /^LABEL/) {
193 $root_link = $rootpart;
194 $root_link =~ s{\"}{}g;
195 $root_link =~ s{^LABEL=}{/dev/disk/by-label/};
196 $root_link =~ s{^UUID=}{/dev/disk/by-uuid/};
199 $root_id = $rootpart;
200 $root_disk = readlink($root_link);
201 $root_disk =~ s{\.\./\.\./}{/dev/};
203 if (-b $root_disk) { $root_dev = $root_disk; }
205 if($opt_v) { print "E: cannot check $root_link: link does not exist!\n"; }
210 print "E: cannot check $root_link: link does not exist!\n";
215 print "E: cannot use uncommon $rootpart found as root device!\n";
231 opendir(MYDH, "$path_id") or die("cannot open $path_id: $! \n");
232 @sellinks = grep(!/\-part\d\d?$/, grep(!/^\.\.?$/, readdir(MYDH)));
233 @sellinks = sort(@sellinks);
236 foreach $_idlink (@sellinks) {
238 if(not $_idlink =~ /^usb/ and length($_idlink) > 10) {
239 $_actlink = readlink("$path_id/$_idlink");
240 $_actlink =~ s{\.\./\.\./}{/dev/};
241 if($opt_v) { print "** try: $_actlink => $_idlink \n"; }
243 # stop if we find the right link...
244 if($_actlink eq $olddev) {
245 $newdevid = $_idlink;
246 if($opt_v) { print "** convert: $_actlink => $path_id/$_idlink \n\n"; }
253 if($opt_v) { print "W: $olddev not converted: link not useful\n\n"; }
259 sub convert_boot_device {
264 # global variables: $boot_dev, $boot_id
267 if ($root_dev =~ /\/dev\/md/) {
268 # search if the found partition is a raid volume
269 $boot_disk = check_raid($root_dev);
272 # find the right block device name
273 $boot_disk = $root_dev;
274 $boot_disk =~ s/\d+$//;
278 # set global variable boot_dev
279 $boot_dev = $boot_disk;
282 print "E: boot device $boot_disk does not exist! \n";
287 print "E: could not find root device $root_dev! \n";
292 if($opt_v) { print "Convert boot option $boot_disk into DISK ID\n"; }
293 $boot_id = $idpath . "/" . find_id_link($boot_disk,$idpath);
295 if(not -l "$boot_id") {
296 if($opt_v) { print "W: could not find DISK ID for $boot_disk!\n"; }
297 ## not so important, than using boot_dev in lilo.conf
312 # check if the found partition is a raid volume
313 if($part =~ /\/dev\/md/)
316 $mdname =~ s/\/dev\///;
318 $md = `grep $mdname /proc/mdstat`;
320 @devices = split(" ", $md);
321 @devices = sort(@devices[4..$#devices]);
322 $part = "/dev/" . $devices[0];
329 sub write_lilo_conf {
332 my $exit = copy_template();
335 # create lilo.conf.new
337 write_image_config();
340 if (-f $liloconf and not -f $liloconfold) {
341 # move old lilo.conf to lilo.conf.old
342 @status = stat($liloconf);
343 move ($liloconf, $liloconfold) or die "Cannot rename file: $!\n";
344 utime ($status[9],$status[9],$liloconfold);
345 chmod (0600,$liloconfold);
346 print "Old file moved to: $liloconfold \n";
348 if (-f $liloconfnew) {
349 move ($liloconfnew, $liloconf) or die "Cannot move file: $!\n";
350 chmod (0600,$liloconf);
351 print "New file created as: $liloconf \n";
352 print "Now you must execute '/sbin/lilo' to " .
353 "activate this new configuation!\n\n";
356 print "E: Cannot find temporary file $conftmp_1!\n";
368 # copy template config
370 system("gzip -d -c $template >$conftmp_1") if ($template =~ /\.gz$/);
371 system("cat $template >$conftmp_1") if ($template =~ /\.conf$/);
373 open(CONFTMP1, "<$conftmp_1") or die "$prog: couldn't open $conftmp_1: $!\n";
374 open(CONFTMP2, ">$conftmp_2") or die "$prog: couldn't open $conftmp_2: $!\n";
377 if (/first\ example/) {
380 unless ($endreached) {
384 close(CONFTMP1) or die "$prog: couldn't close $conftmp_1: $!\n";;
385 close(CONFTMP2) or die "$prog: couldn't close $conftmp_2: $!\n";;
388 open(CONFTMP2, ">$conftmp_2") or die "$prog: couldn't open $conftmp_2: $!\n";
389 print CONFTMP2 "# /etc/lilo.conf
391 ### LILO global section ###
398 menu-scheme = Wb:Yr:Wb:Wb
404 ### LILO per-image section ###
407 close(CONFTMP2) or die "$prog: couldn't close $conftmp_2: $!\n";;
413 sub write_boot_option {
419 open(MYFH_NEW, "> $liloconfnew") or die "Cannot open file: $!";
420 open(MYFH_TMP, "< $conftmp_2") or die "Cannot read file: $!";
423 # line read from MYFH_TMP
426 if (/^boot/ and $ok == 0) {
428 $oldline = "#boot = $boot_dev\n";
429 $newline = "boot = $boot_id\n";
430 print MYFH_NEW $oldline;
431 if($opt_v) { print $oldline; }
434 $oldline = "boot = $boot_dev\n";
436 print MYFH_NEW $newline;
437 if($opt_v) { print $newline; }
438 if($opt_v) { print "\n"; }
440 # convert only one time
444 print MYFH_NEW $oldline;
451 sub write_image_config {
458 # search for kernel image files
459 my @vmlinuz = readpipe("/bin/ls -t -1 /boot/vmlinuz-2* 2>/dev/null");
461 # append to new lilo.conf
462 open(MYFH_NEW, ">> $liloconfnew") or die "Cannot open file: $!";
464 # create some line for each kernel image
466 foreach $image (@vmlinuz) {
467 # search for kernel initrd file
470 $initrd =~ s/vmlinuz/initrd\.img/;
473 print MYFH_NEW 'image = ' . $image . "\n";
474 if($opt_v) { print 'image = ' . $image . "\n"; }
476 print MYFH_NEW "\t" . 'label = "Linux"' . "\n";
477 if($opt_v) { print "\t" . 'label = "Linux"' . "\n"; }
480 print MYFH_NEW "\t" . 'label = "Linux Old"' . "\n";
481 if($opt_v) { print "\t" . 'label = "Linux Old"' . "\n"; }
484 print MYFH_NEW "\t" . '#root = ' . $root_dev . "\n";
485 if($opt_v) { print "\t" . '#root = ' . $root_dev . "\n"; }
486 print MYFH_NEW "\t" . 'root = "' . $root_id . '"' . "\n";
487 if($opt_v) { print "\t" . 'root = "' . $root_id . '"' . "\n"; }
490 print MYFH_NEW "\t" . 'root = ' . $root_dev . "\n";
491 if($opt_v) { print "\t" . 'root = ' . $root_dev . "\n"; }
493 print MYFH_NEW "\t" . 'read-only' . "\n";
494 if($opt_v) { print "\t" . 'read-only' . "\n"; }
495 print MYFH_NEW "#\t" . 'restricted' . "\n";
496 if($opt_v) { print "#\t" . 'restricted' . "\n"; }
497 print MYFH_NEW "#\t" . 'alias = ' . "$nr2" . "\n";
498 if($opt_v) { print "#\t" . 'alias = ' . "$nr2" . "\n"; }
499 print MYFH_NEW "#\t" . 'optional' . "\n";
500 if($opt_v) { print "#\t" . 'optional' . "\n"; }
502 print MYFH_NEW "\t" . 'initrd = ' . $initrd . "\n";
503 if($opt_v) { print "\t" . 'initrd = ' . $initrd . "\n"; }
506 if($opt_v) { print "\n"; }
523 liloconfig - create new lilo.conf file (with diskid and uuid)
527 liloconfig [-h] [-v] [-f] [lilo.conf]
531 liloconfig is an simple program for creating a new lilo.conf file.
532 After creating the new configuration file you must execute '/sbin/lilo'.
534 liloconfig use the lilo.example.conf file as template. In the final
535 lilo.conf file you find many useful comments for custom changes.
539 Lines in the configuration file /etc/lilo.conf:
541 ### LILO global section ###
548 menu-scheme = Wb:Yr:Wb:Wb
554 ### LILO per-image section ###
557 boot = /dev/disk/by-id/ata-SAMSUNG_SV1604N_S01FJ10X999999
559 image = /boot/vmlinuz-2.6.32-5book-686
562 root = "UUID=18843936-00f9-4df0-a373-000d05a5dd44"
567 initrd = /boot/initrd.img-2.6.32-5book-686
569 image = /boot/vmlinuz-2.6.32-5-686
572 root = "UUID=18843936-00f9-4df0-a373-000d05a5dd44"
577 initrd = /boot/initrd.img-2.6.32-5-686
589 Print verbose messages.
593 Force overriding existing lilo.conf.
599 B<liloconfig> was written by Joachim Wiedorn.