Add new script liloconfig
authorJoachim Wiedorn <ad_debian@joonet.de>
Sun, 20 Mar 2011 14:41:31 +0000 (15:41 +0100)
committerJoachim Wiedorn <ad_debian@joonet.de>
Sun, 20 Mar 2011 14:41:31 +0000 (15:41 +0100)
debian/changelog
debian/manpages/liloconfig.8
debian/scripts/liloconfig

index 169f2be86efeb8b2d92853b57bd8b005524915cc..b2b2654b6ec9f06b373212bff4a7594279c7e3ea 100644 (file)
@@ -26,8 +26,10 @@ lilo (1:23.1-2) unstable; urgency=low
     - Update of Italian translation (it.po). (Closes: #618801)
     - Update of Brazilian Portuguese translation. (Closes: #618738)
     - Update of Swedish translation (sv.po). (Closes: #618620)
+  * Add new script liloconfig, using template with comments,
+      works with UUID, LABEL and disk-id for root and boot options.
 
- -- Joachim Wiedorn <ad_debian@joonet.de>  Sat, 19 Mar 2011 23:34:00 +0100
+ -- Joachim Wiedorn <ad_debian@joonet.de>  Sat, 19 Mar 2011 23:50:00 +0100
 
 lilo (1:23.1-1) unstable; urgency=low
 
index 731aba92ad6b929ff1d47fd9728f787de0b2ecba..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,83 +0,0 @@
-'\" t
-.\" This page is not actually based on the original LILO docs,
-.\" but I'm using the same COPYING conditions:
-.\"
-.\" This manual page is:
-.\"  Copyright 1999 Peter Maydell <pmaydell@chiark.greenend.org.uk>
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms of parts of or the
-.\" whole original or derived work are permitted provided that the
-.\" original work is properly attributed to the author. The name of the
-.\" author may not be used to endorse or promote products derived from
-.\" this software without specific prior written permission. This work
-.\" is provided "as is" and without any express or implied warranties.
-.\"
-.TH LILOCONFIG 8 "September 1999"
-.SH NAME
-liloconfig \- interactive configure script for lilo
-.SH SYNOPSIS
-.B liloconfig
-.SH DESCRIPTION
-.LP
-.B liloconfig
-is an interactive program which will ask you a series of questions
-and write a
-.B lilo.conf(5)
-configuration file for you. It will also set up the Master Boot Record
-(MBR) so that Linux will boot from hard disk.
-It is normally run automatically whenever you upgrade the
-.B lilo(8)
-Debian package.
-
-The configuration file generated by
-.B liloconfig
-is intended for common installations; if your setup is complicated
-or unusual you should consider writing your own customised
-.B lilo.conf.
-To do this you should refer to the comprehensive
-.B lilo
-documentation, which can be found in
-/usr/share/doc/lilo/ on Debian systems.
-
-If you have already written your own
-.B lilo.conf
-then the script will ask you if you wish to keep it, in which case
-it will check it for options which are incompatible with the current
-version of
-.B lilo
-and run
-.B lilo
-to install the boot block.
-
-If you have no
-.B lilo.conf
-or choose to overwrite it,
-.B liloconfig
-will perform three operations to ensure that the Linux system will
-boot from the hard disk:
-install LILO in the Linux partition's boot record, install a
-simple MBR, and mark the Linux partition as the active partition.
-You will be prompted prior to each of these operations, so you
-can skip them and perform them manually later on.
-
-The automatically generated
-.B lilo.conf
-contains helpful comments, so it might well be a good place to start
-even if you wish to roll your own configuration file.
-
-.SH AUTHOR
-Bruce Perens <bruce@Pixar.com>,
-.br
-Bernd Eckenfels <ecki@debian.org>
-.br
-and Vincent Renardias <vincent@ldsol.com>.
-
-Peter Maydell (pmaydell@chiark.greenend.org.uk) wrote this manual page.
-.SH SEE ALSO
-.BR lilo (8),
-.BR lilo.conf (5)
-
-.B lilo
-comes with extensive documentation; this can be found in
-/usr/share/doc/lilo/ on Debian systems.
index 7becf555c405e35cacab8f4f68d29fb4f28cd4c3..46a83f512d0ad44e55f8e29cf0b1f46a67cd1a3c 100644 (file)
@@ -1,3 +1,601 @@
 #!/usr/bin/perl -w
 
+#       liloconfig -  creating a new lilo.conf file
+#       
+#       Copyright 2011 Joachim Wiedorn <ad_debian@joonet.de>
+#       
+#       This program is free software; you can redistribute it and/or modify
+#       it under the terms of the GNU General Public License as published by
+#       the Free Software Foundation; either version 2 of the License, or
+#       (at your option) any later version.
+#       
+#       This program is distributed in the hope that it will be useful,
+#       but WITHOUT ANY WARRANTY; without even the implied warranty of
+#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#       GNU General Public License for more details.
+#       
+#       You should have received a copy of the GNU General Public License
+#       along with this program; if not, write to the Free Software
+#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+#       MA 02110-1301, USA.
+
+#---- some modules
+use strict;
+use warnings;
+use Getopt::Std;
+use Pod::Usage;
+use File::Copy;
+
+
+#---- global variables
+my $prog = $0;
+$prog =~ s#.*/##;
+my $version = "0.1";
+
+#---- parameter check
+# h: help, v: verbose, f: force
+our $opt_h = 0;
+our $opt_v = 0;
+our $opt_f = 0;
+getopts('hvf');
+# define perldoc usage
+pod2usage(1) if $opt_h;
+
+#---- other variables
+our $liloconf  = "/etc/lilo.conf";
+our $conftmp_1 = "/tmp/lilotmp1";
+our $conftmp_2 = "/tmp/lilotmp2";
+our $liloconfold = $liloconf . ".old";
+our $liloconfnew = $liloconf . ".new";
+our $fstabconf = "/etc/fstab";
+
+our $idpath = "/dev/disk/by-id";
+our $uuidpath = "/dev/disk/by-uuid";
+our $lblpath = "/dev/disk/by-label";
+our $template = "/usr/share/doc/lilo/examples/lilo.example.conf.gz";
+
+our $rootpart;    # found root part
+our $root_dev;    # /dev/hdX9, /dev/sdX9, /dev/md/*
+our $root_id;     # UUID, LABEL, ID
+our $boot_dev;    # /dev/hdX, /dev/sdX, /dev/md
+our $boot_id;     # DISK-ID
+
+#-------------------- main program --------------------
+
+sub main {
+
+       my $exit = 0;
+
+       if (@ARGV == 1) {
+               $liloconf = "$ARGV[0]";
+               $liloconfold = $liloconf . ".old";
+               $liloconfnew = $liloconf . ".new";
+       }
+       if (-f $liloconf and not $opt_f) {
+               print "$prog: $liloconf already exist! Please use '-f' for overwriting.\n";
+               $exit = 1;
+       }
+       else {
+               $exit = create_lilo_conf()
+       }               
+       return $exit;
+}
+
+#-------------------- subroutines --------------------
+
+sub create_lilo_conf {
+       
+       my $found = 0;
+       my $exit = 1;
+
+       # search for root device in fstab and convert it
+       $found = detect_root_device();
+
+       # convert root device to boot device
+       if ($found) { $found = convert_boot_device(); }
+
+       # finally write new lilo.conf file
+       if ($found) { $exit = write_lilo_conf(); }
+
+       return $exit;
+}
+
+sub detect_root_device {
+       
+       # read fstab and find root device; 
+       my $found = read_fstab();
+
+       # identify root device: root_dev and root_id
+       if ($found) { $found = convert_root_device(); }
+       
+       return $found;
+}
+
+sub read_fstab {
+       
+       my $root_part;
+       my $mountpoint;
+       my $broken_fstab = 1;
+       my $base_fstab = 0;
+       my $found = 1;
+
+       # check fstab for root device
+       if (-f $fstabconf) {
+               # Parsing fstab for the root partition
+               open(FSTAB, "<$fstabconf") or die "$prog: couldn't open $fstabconf: $!\n";
+
+               while (<FSTAB>) {
+                       # Search magic string which indicates a base filesystem
+                       $base_fstab = 1 if /^# UNCONFIGURED FSTAB FOR BASE SYSTEM/;
+                       next if /^#/;     # ignore comment lines
+
+                       s/^[ \t]+//;      # remove space or tab at begin of the line
+                       ($root_part,$mountpoint) = split(/[ \t]+/);
+                       next unless defined $mountpoint;    # ignore empty lines too
+
+                       # stop if we found the root device...
+                       if ($mountpoint eq '/') {
+                               $broken_fstab = 0;
+                               last;
+                       }
+               }
+               close(FSTAB) or die "$prog: couldn't close $fstabconf: $!\n";
+       }
+
+       if ($base_fstab) {
+               print "E: It seems you want configure the base filesystem \n" .
+                     "and I'm therefore simply going to exit successfully \n" .
+                     "without trying to actually configure LILO properly. \n";
+               $found = 0;
+       }
+       if ($broken_fstab) {
+               print "E: It seems the file /etc/fstab is not properly \n" .
+                     "configured: no root partition '/' found! \n";
+               $found = 0;
+       }
+       # save the found root device
+       $rootpart = $root_part;
+
+       return $found;
+}
+
+sub convert_root_device {
+       
+       my $found = 1;
+       my $root_disk = '';
+       my $root_link;
+       # global variables: $root_dev, $root_id
+
+       if ($rootpart =~ /\/dev\//) {
+               $root_disk = $rootpart;
+
+               if (-b $root_disk) {
+                       $root_dev = $root_disk;
+                       if($opt_v) { print "Convert root option $root_disk into UUID\n"; }
+                       $root_id = find_id_link($root_disk,$uuidpath);
+
+                       if (not -l "$uuidpath/$root_id") {
+                               if($opt_v) { print "W: could not find UUID for $root_disk!\n"; }
+                               ## than we want use root_dev in lilo.conf
+                               #$found = 0;
+                       }
+                       else {
+                               # finally add uuid label
+                               $root_id = "UUID=" . $root_id;
+                       }
+               }
+               else {
+                       if($opt_v) { print "E: cannot check $root_disk: device does not exist!\n"; }
+                       $found = 0;
+               }
+       }
+       elsif ($rootpart =~ /^UUID/ or $rootpart =~ /^LABEL/) {
+               $root_link = $rootpart;
+               $root_link =~ s{\"}{}g;
+               $root_link =~ s{^LABEL=}{/dev/disk/by-label/};
+               $root_link =~ s{^UUID=}{/dev/disk/by-uuid/};
+
+               if (-l $root_link) {
+                       $root_id = $rootpart;
+                       $root_disk = readlink($root_link);
+                       $root_disk =~ s{\.\./\.\./}{/dev/};
+
+                       if (-b $root_disk) { $root_dev = $root_disk; }
+                       else {
+                               if($opt_v) { print "E: cannot check $root_link: link does not exist!\n"; }
+                               $found = 0;
+                       }
+               }
+               else {
+                       print "E: cannot check $root_link: link does not exist!\n";
+                       $found = 0;
+               }
+       }
+       else {
+               print "E: cannot use uncommon $rootpart found as root device!\n";
+               $found = 0;
+       }
+
+       return $found;
+}
+
+sub find_id_link {
+       
+       my $olddev = $_[0];
+       my $path_id = $_[1];
+       my @sellinks;
+       my $_idlink;
+       my $_actlink;
+       my $newdevid = '';
+
+       opendir(MYDH, "$path_id") or die("cannot open $path_id: $! \n");
+       @sellinks = grep(!/\-part\d\d?$/, grep(!/^\.\.?$/, readdir(MYDH)));
+       @sellinks = sort(@sellinks);
+       closedir(MYDH);
+
+       foreach $_idlink (@sellinks) {
+               chomp $_idlink;
+               if(not $_idlink =~ /^usb/ and length($_idlink) > 10) {
+                       $_actlink = readlink("$path_id/$_idlink");
+                       $_actlink =~ s{\.\./\.\./}{/dev/};
+                       if($opt_v) { print "** try: $_actlink => $_idlink \n"; }
+                       
+                       # stop if we find the right link...
+                       if($_actlink eq $olddev) {
+                               $newdevid = $_idlink;
+                               if($opt_v) { print "** convert: $_actlink => $path_id/$_idlink \n\n"; }
+                               last;
+                       }
+               }
+       }
+
+       if(not $newdevid) {
+               if($opt_v) { print "W: $olddev not converted: link not useful\n\n"; }
+       }
+       
+       return ($newdevid);
+}
+
+sub convert_boot_device {
+
+       my $found = 1;
+       my $boot_disk = '';
+       my $boot_link;
+       # global variables: $boot_dev, $boot_id
+
+       if (-b $root_dev) {
+               if ($root_dev =~ /\/dev\/md/) {
+                       # search if the found partition is a raid volume
+                       $boot_disk = check_raid($root_dev);
+               }
+               else {
+                       # find the right block device name
+                       $boot_disk = $root_dev;
+                       $boot_disk =~ s/\d+$//;
+               }
+
+               if (-b $boot_disk) {
+                       # set global variable boot_dev
+                       $boot_dev = $boot_disk;
+               }
+               else { 
+                       print "E: boot device $boot_disk does not exist! \n";
+                       $found = 0;
+               }
+       }
+       else {
+               print "E: could not find root device $root_dev! \n";
+               $found = 0;
+       }
+
+       if ($found) {
+               if($opt_v) { print "Convert boot option $boot_disk into DISK ID\n"; }
+               $boot_id = $idpath . "/" . find_id_link($boot_disk,$idpath);
+
+               if(not -l "$boot_id") {
+                       if($opt_v) { print "W: could not find DISK ID for $boot_disk!\n"; }
+                       ## not so important, than using boot_dev in lilo.conf
+                       #$found = 0;
+               }
+       }
+
+       return $found;
+}
+
+sub check_raid {
+       
+       my $part = $_[0];
+       my $mdname;
+       my $md;
+       my @devices;
+
+       # check if the found partition is a raid volume
+       if($part =~ /\/dev\/md/)
+       {
+               $mdname = $part;
+               $mdname =~ s/\/dev\///;
+               $mdname =~ s/\///;
+               $md = `grep $mdname /proc/mdstat`;
+       
+               @devices = split(" ", $md);
+               @devices = sort(@devices[4..$#devices]);
+               $part = "/dev/" . $devices[0];
+               $part =~ s/\[.*$//;
+
+       }
+       return $part;
+}
+
+sub write_lilo_conf {
+       
+       my @status;
+       my $exit = copy_template();
+
+       if (not $exit) {
+               # create lilo.conf.new
+               write_boot_option();
+               write_image_config();
+       }
+
+       if (-f $liloconf and not -f $liloconfold) {
+               # move old lilo.conf to lilo.conf.old
+               @status = stat($liloconf);
+               move ($liloconf, $liloconfold) or die "Cannot rename file: $!\n";
+               utime ($status[9],$status[9],$liloconfold);
+               chmod (0600,$liloconfold);
+               print "Old file moved to: $liloconfold \n";
+       }
+       if (-f $liloconfnew) {
+               move ($liloconfnew, $liloconf) or die "Cannot move file: $!\n";
+               chmod (0600,$liloconf);
+               print "New file created as: $liloconf \n";
+               print "Now you must execute '/sbin/lilo' to " . 
+                     "activate this new configuation!\n\n";
+       }
+       else {
+               print "E: Cannot find temporary file $conftmp_1!\n";
+               $exit = 1;
+       }
+       
+       return $exit;
+}
+
+sub copy_template {
+
+       my $endreached = 0;
+       my $exit = 0;
+       
+       # copy template config
+       if (-f $template) {
+               system("gzip -d -c $template >$conftmp_1") if ($template =~ /\.gz$/);
+               system("cat $template >$conftmp_1") if ($template =~ /\.conf$/);
+
+               open(CONFTMP1, "<$conftmp_1") or die "$prog: couldn't open $conftmp_1: $!\n";
+               open(CONFTMP2, ">$conftmp_2") or die "$prog: couldn't open $conftmp_2: $!\n";
+
+               while (<CONFTMP1>) {
+                       if (/first\ example/) {
+                               $endreached = 1;
+                       }
+                       unless ($endreached) {
+                               print CONFTMP2 $_;
+                       }
+               }
+               close(CONFTMP1) or die "$prog: couldn't close $conftmp_1: $!\n";;
+               close(CONFTMP2) or die "$prog: couldn't close $conftmp_2: $!\n";;
+       }
+       else {
+               open(CONFTMP2, ">$conftmp_2") or die "$prog: couldn't open $conftmp_2: $!\n";
+               print CONFTMP2 "# /etc/lilo.conf
+
+### LILO global section ###
+
+#large-memory
+lba32
+boot = /dev/sda
+map = /boot/map
+install = menu
+menu-scheme = Wb:Yr:Wb:Wb
+prompt
+timeout = 100
+vga = normal
+#default = Linux
+
+### LILO per-image section ###
+
+"; 
+               close(CONFTMP2) or die "$prog: couldn't close $conftmp_2: $!\n";;
+       }
+       
+       return $exit;
+}
+
+sub write_boot_option {
+       
+       my $oldline = '';
+       my $newline = '';
+       my $ok = 0;
+
+       open(MYFH_NEW, "> $liloconfnew") or die "Cannot open file: $!";
+       open(MYFH_TMP, "< $conftmp_2") or die "Cannot read file: $!";
+
+       while (<MYFH_TMP>) {
+               # line read from MYFH_TMP
+               $oldline = $_;
+
+               if (/^boot/ and $ok == 0) {
+                       if ($boot_id) {
+                               $oldline = "#boot = $boot_dev\n";
+                               $newline = "boot = $boot_id\n";
+                               print MYFH_NEW $oldline;
+                               if($opt_v) { print $oldline; }
+                       }
+                       else {
+                               $oldline = "boot = $boot_dev\n";
+                       }
+                       print MYFH_NEW $newline;
+                       if($opt_v) { print $newline; }
+                       if($opt_v) { print "\n"; }
+
+                       # convert only one time
+                       $ok = 1;
+               }
+               else {
+                       print MYFH_NEW $oldline;
+               }
+       }
+       close(MYFH_TMP);
+       close(MYFH_NEW);
+}
+
+sub write_image_config {
+
+       my $image;
+       my $initrd;
+       my $nr;
+       my $nr2;
+
+       # search for kernel image files
+       my @vmlinuz = readpipe("/bin/ls -t -1 /boot/vmlinuz-2* 2>/dev/null");
+
+       # append to new lilo.conf
+       open(MYFH_NEW, ">> $liloconfnew") or die "Cannot open file: $!";
+
+       # create some line for each kernel image
+       $nr = 0;
+       foreach $image (@vmlinuz) {
+               # search for kernel initrd file
+               chomp $image;
+               $initrd = $image;
+               $initrd =~ s/vmlinuz/initrd\.img/;
+               $nr2 = $nr + 1;
+
+                       print MYFH_NEW     'image = ' . $image . "\n";
+                       if($opt_v) { print 'image = ' . $image . "\n"; }
+               if ($nr == 0) {
+                       print MYFH_NEW     "\t"  . 'label = "Linux"' . "\n";
+                       if($opt_v) { print "\t"  . 'label = "Linux"' . "\n"; }
+               }
+               elsif ($nr == 1) {
+                       print MYFH_NEW     "\t"  . 'label = "Linux Old"' . "\n";
+                       if($opt_v) { print "\t"  . 'label = "Linux Old"' . "\n"; }
+               }
+               if ($root_id) {
+                       print MYFH_NEW     "\t"  . '#root = ' . $root_dev . "\n";
+                       if($opt_v) { print "\t"  . '#root = ' . $root_dev . "\n"; }
+                       print MYFH_NEW     "\t"  . 'root = "' . $root_id . '"' . "\n";
+                       if($opt_v) { print "\t"  . 'root = "' . $root_id . '"' . "\n"; }
+               }
+               else {
+                       print MYFH_NEW     "\t"  . 'root = ' . $root_dev . "\n";
+                       if($opt_v) { print "\t"  . 'root = ' . $root_dev . "\n"; }
+               }
+                       print MYFH_NEW     "\t"  . 'read-only' . "\n";
+                       if($opt_v) { print "\t"  . 'read-only' . "\n"; }
+                       print MYFH_NEW     "#\t" . 'restricted' . "\n";
+                       if($opt_v) { print "#\t" . 'restricted' . "\n"; }
+                       print MYFH_NEW     "#\t" . 'alias = ' . "$nr2" . "\n";
+                       if($opt_v) { print "#\t" . 'alias = ' . "$nr2" . "\n"; }
+                       print MYFH_NEW     "#\t" . 'optional' . "\n";
+                       if($opt_v) { print "#\t" . 'optional' . "\n"; }
+               if (-f $initrd) {
+                       print MYFH_NEW     "\t"  . 'initrd = ' . $initrd . "\n";
+                       if($opt_v) { print "\t"  . 'initrd = ' . $initrd . "\n"; }
+               }
+                       print MYFH_NEW     "\n";
+                       if($opt_v) { print "\n"; }
+
+               $nr++;
+               last if ($nr > 1);
+       }
+
+       close(MYFH_NEW);
+}              
+               
+       
+main();
+
 __END__
+
+
+=head1 NAME
+
+liloconfig - create new lilo.conf file (with diskid and uuid)
+
+=head1 SYNOPSIS
+
+liloconfig [-h] [-v] [-f] [lilo.conf]
+
+=head1 DESCRIPTION
+
+liloconfig is an simple program for creating a new lilo.conf file.
+After creating the new configuration file you must execute '/sbin/lilo'.
+
+liloconfig use the lilo.example.conf file as template. In the final
+lilo.conf file you find many useful comments for custom changes.
+
+=head1 EXAMPLES
+
+Lines in the configuration file /etc/lilo.conf:
+
+  ### LILO global section ###
+
+  #large-memory
+  lba32
+  boot = /dev/sda
+  map = /boot/map
+  install = menu
+  menu-scheme = Wb:Yr:Wb:Wb
+  prompt
+  timeout = 100
+  vga = normal
+  #default = Linux
+
+  ### LILO per-image section ###
+
+  #boot = /dev/sda
+  boot = /dev/disk/by-id/ata-SAMSUNG_SV1604N_S01FJ10X999999
+
+  image = /boot/vmlinuz-2.6.32-5book-686
+      label = "Linux"
+      #root = /dev/sda1
+      root = "UUID=18843936-00f9-4df0-a373-000d05a5dd44"
+      read-only
+  #   restricted
+  #   alias = 1
+  #   optional
+      initrd = /boot/initrd.img-2.6.32-5book-686
+
+  image = /boot/vmlinuz-2.6.32-5-686
+      label = "Linux Old"
+      #root = /dev/sda1
+      root = "UUID=18843936-00f9-4df0-a373-000d05a5dd44"
+      read-only
+  #   restricted
+  #   alias = 2
+  #   optional
+      initrd = /boot/initrd.img-2.6.32-5-686
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-h>
+
+Print a brief help.
+
+=item B<-v>
+
+Print verbose messages.
+
+=item B<-f>
+
+Force overriding existing lilo.conf.
+
+=back
+
+=head1 AUTHOR
+
+B<liloconfig> was written by Joachim Wiedorn.
+
+=cut