From 511a6cbff1026487ac9c9fffbad5a51e003a88e4 Mon Sep 17 00:00:00 2001 From: Joachim Wiedorn Date: Thu, 18 Nov 2010 22:41:42 +0100 Subject: [PATCH] Add lilo-uuid-diskid script with manpage --- debian/changelog | 1 + debian/manpages/lilo-uuid-diskid.8 | 122 +++++++ debian/manpages/lilo-uuid-diskid.pod | 75 +++++ debian/scripts/lilo-uuid-diskid | 463 +++++++++++++++++++++++++++ 4 files changed, 661 insertions(+) create mode 100644 debian/manpages/lilo-uuid-diskid.8 create mode 100644 debian/manpages/lilo-uuid-diskid.pod create mode 100644 debian/scripts/lilo-uuid-diskid diff --git a/debian/changelog b/debian/changelog index 6aaed9f..ff0ebb0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -29,6 +29,7 @@ lilo (1:23.1-1) unstable; urgency=low * Remove some obsolete manpages. * Move script liloconfig into directory debian/scripts. * Add new script update-lilo and its manual page. + * Add new script lilo-uuid-diskid for ID conversion and its manual page. -- Joachim Wiedorn Thu, 18 Nov 2010 20:32:02 +0100 diff --git a/debian/manpages/lilo-uuid-diskid.8 b/debian/manpages/lilo-uuid-diskid.8 new file mode 100644 index 0000000..d601435 --- /dev/null +++ b/debian/manpages/lilo-uuid-diskid.8 @@ -0,0 +1,122 @@ +.\" Automatically generated by Pod::Man 2.1801 (Pod::Simple 3.07) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" ======================================================================== +.\" +.IX Title "LILO-UUID-DISKID 8" +.TH LILO-UUID-DISKID 8 "2010-07-24" "23.0" "lilo documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +lilo\-uuid\-diskid \- convert boot / root options to diskid and uuid in lilo.conf. +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +lilo-uuid-diskid [\-h] [\-v] [lilo.conf] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +This script looks for the boot block device or boot partition and create the +right diskid or uuid as boot option. Then it looks for all root partitions +and create the right uuids as root options. +.PP +These conversions are necessary for use with newer kernel (>= 2.6.26) if it +use the libata module for parallel and serial \s-1ATA\s0 interfaces of block devices +(i. e. hard disks with \s-1IDE\s0 or \s-1SATA\s0 interface, usbsticks). +.SH "OPTIONS" +.IX Header "OPTIONS" +.IP "\fB\-h\fR" 4 +.IX Item "-h" +Print a brief help. +.IP "\fB\-v\fR" 4 +.IX Item "-v" +Print verbose messages. +.SH "EXAMPLES" +.IX Header "EXAMPLES" +Lines in the configuration file /etc/lilo.conf: +.PP +.Vb 2 +\& #boot = /dev/sda +\& boot = /dev/disk/by\-id/ata\-SAMSUNG_SV1604N_S01FJ10X999999 +\& +\& #root = /dev/sda1 +\& root = "UUID=/dev/disk/by\-uuid/18843936\-00f9\-4df0\-a373\-000d05a5dd44" +.Ve +.SH "COPYRIGHT and LICENSE" +.IX Header "COPYRIGHT and LICENSE" +Copyright (C) 2010 Joachim Wiedorn +.PP +This script is free software; you can redistribute it and/or modify +it under the terms of the \s-1GNU\s0 General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. +.PP +On Debian systems, the complete text of the \s-1GNU\s0 General Public +License version 2 can be found in `/usr/share/common\-licenses/GPL\-2'. +.SH "AUTHOR" +.IX Header "AUTHOR" +\&\fBlilo-uuid-diskid\fR was written by Joachim Wiedorn. +.PP +This manual page was written by Joachim Wiedorn +for the Debian project (and may be used by others). +.SH "SEE ALSO" +.IX Header "SEE ALSO" +\&\fBlilo\fR(8), \fBupdate-lilo\fR(8) diff --git a/debian/manpages/lilo-uuid-diskid.pod b/debian/manpages/lilo-uuid-diskid.pod new file mode 100644 index 0000000..a741bfe --- /dev/null +++ b/debian/manpages/lilo-uuid-diskid.pod @@ -0,0 +1,75 @@ +=for header +manpage: LILO-UUID-DISKID +section: 8 +title: lilo documentation +version: 23.0 +datum: 2010-07-24 + +=encoding utf8 + +=head1 NAME + +lilo-uuid-diskid - convert boot / root options to diskid and uuid in lilo.conf. + +=head1 SYNOPSIS + +lilo-uuid-diskid [-h] [-v] [lilo.conf] + +=head1 DESCRIPTION + +This script looks for the boot block device or boot partition and create the +right diskid or uuid as boot option. Then it looks for all root partitions +and create the right uuids as root options. + +These conversions are necessary for use with newer kernel (>= 2.6.26) if it +use the libata module for parallel and serial ATA interfaces of block devices +(i. e. hard disks with IDE or SATA interface, usbsticks). + +=head1 OPTIONS + +=over 4 + +=item B<-h> + +Print a brief help. + +=item B<-v> + +Print verbose messages. + +=back + +=head1 EXAMPLES + +Lines in the configuration file /etc/lilo.conf: + + #boot = /dev/sda + boot = /dev/disk/by-id/ata-SAMSUNG_SV1604N_S01FJ10X999999 + + #root = /dev/sda1 + root = "UUID=/dev/disk/by-uuid/18843936-00f9-4df0-a373-000d05a5dd44" + +=head1 COPYRIGHT and LICENSE + +Copyright (C) 2010 Joachim Wiedorn + +This script 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. + +On Debian systems, the complete text of the GNU General Public +License version 2 can be found in `/usr/share/common-licenses/GPL-2'. + +=head1 AUTHOR + +B was written by Joachim Wiedorn. + +This manual page was written by Joachim Wiedorn +for the Debian project (and may be used by others). + +=head1 SEE ALSO + +B(8), B(8) + +=cut diff --git a/debian/scripts/lilo-uuid-diskid b/debian/scripts/lilo-uuid-diskid new file mode 100644 index 0000000..5b79f9f --- /dev/null +++ b/debian/scripts/lilo-uuid-diskid @@ -0,0 +1,463 @@ +#!/usr/bin/perl -w + +# lilo-uuid-diskid - convert boot / root options to diskid and +# uuid in lilo.conf +# +# Copyright 2010 Joachim Wiedorn +# +# 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 +our $opt_h = 0; +our $opt_v = 0; +getopts('hv'); +# define perldoc usage +pod2usage(1) if $opt_h; + +#---- other variables +our $liloconf = "/etc/lilo.conf"; +our $liloconfold = ''; +our $fstabconf = "/etc/fstab"; +our $idpath = "/dev/disk/by-id"; +our $uuidpath = "/dev/disk/by-uuid"; + +our $bootready = 0; +our $boot_id = ''; +our $root_id = ''; +our $optboot = 0; # -1 = only ^#boot, 0 = nothing, 1 = ^boot exist + +#-------------------- main program -------------------- + +sub main { + + my $exit = 0; + + if (@ARGV == 1) { + $liloconf = "$ARGV[0]"; + } + + if (-f $liloconf) { + $liloconfold = $liloconf . "_old"; + $exit = convert_lilo_conf(); + } + else { + print "cannot open $liloconf: file not found!\n"; + $exit = 1; + } + return $exit; +} + +#-------------------- subroutines -------------------- + +sub convert_lilo_conf { + + my @sellines; + my $exit = 0; + my $line = ''; + my $bootline = ''; + + # at first read lilo.conf and search for 'boot' + my $ok = 0; + open(MYFH, "<$liloconf") or die ("cannot open $liloconf: $!"); + @sellines = grep(/^#?boot/, readline(MYFH)); + close(MYFH); + + # analyse the boot option in config file + foreach $line (@sellines) { + if ($line =~ /^boot/) { + # activated boot option found + $bootline = $line; + chomp $bootline; + $optboot = 1; + } + if ($optboot == 0) { + # commented boot option found + if ($line =~ /^#boot/) { $optboot = -1; } + } + } + + if ($optboot != 0) { + + if($opt_v) { print "++++++++++ write options into $liloconf ++++++++++\n\n"; } + + if ( detect_boot_device($bootline) == 0) { + # found diskid or uuid for boot device: $boot_id + if (-l $boot_id) { + write_boot_option(); + } + else { + if($opt_v) { print "cannot open $boot_id: link does not exist!\n"; } + $exit = 1; + } + } + else { + if($opt_v) { print "\n"; } + } + } + else { + print "cannot use $liloconf: uncomplete configuration!\n"; + $exit = 1; + } + + return $exit; +} + + +sub detect_boot_device { + + my $boot_line = $_[0]; + my $boot_disk = ''; + my $searchpath; + my $_part; + my $exit = 0; + + if ($optboot == 1) { + # the usual case: found ^boot in lilo.conf + $boot_disk = ($boot_line =~ /^boot *= *(\/dev\/.*)/) ? ($1) : (); + + # check if the found partition is a raid volume + if($boot_disk =~ /\/dev\/md/) { + $boot_disk = check_raid($boot_disk); + } + } + elsif ($optboot == -1) { + # found only ^#boot in lilo.conf, then /etc/fstab is needed + if (-f $fstabconf) { + if($opt_v) { + print "no boot option in $liloconf: selecting from $fstabconf\n"; + } + $boot_disk = read_fstab($fstabconf); + } + else { + print "no boot option in $liloconf and no file $fstabconf found!\n"; + $exit = 1; + } + } + + if (-b $boot_disk) { + if($boot_disk =~ /$idpath/ or $boot_disk =~ /$uuidpath/) { + print "boot option is already updated to $boot_disk\n"; + $bootready = 1; $exit = 1; + } + else { + if($opt_v) { print "convert boot option $boot_disk into new ID\n"; } + + # is it a block device name ? + $_part = $boot_disk; + $_part =~ s/\d+$//; + $searchpath = ($_part eq $boot_disk) ? $idpath : $uuidpath; + + $boot_id = $searchpath . "/" . find_id_link($boot_disk,$searchpath); + if(not -l "$boot_id") { $exit = 1; } + } + } + else { + if($opt_v) { print "cannot read $boot_disk: link does not exist!\n"; } + $exit = 1; + } + return $exit; +} + + +sub read_fstab { + + my $ffile = $_[0]; + my $root_line; + my $root_part; + my $_item; + + $root_line = `awk '{ if (\$2=="/") print \$1}' <$ffile`; + + # search for the last valid entry in /etc/fstab about root partition + foreach $_item (split("\n", $root_line)) { + if(not $_item =~ /#/) { + $root_part = $_item; + } + } + # check if the found partition is a raid volume + if($root_part =~ /\/dev\/md/) { + $root_part = check_raid($root_part); + } + # now find the right block device name + $root_part =~ s/\d+$//; + $root_part =~ s/part$/disc/; + + return $root_part; +} + +sub check_raid { + + my $part = $_[0]; + + # check if the found partition is a raid volume + if($part =~ /\/dev\/md/) + { + my $mdname; + my $md; + my @devices; + + $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 detect_root_device { + + my $root_line = $_[0]; + my $root_disk = ''; + my $exit = 0; + + if (not $exit) { + # extract the root device name + $root_disk = ($root_line =~ /^\t?root *= *(\/dev\/.*)/) ? ($1) : (); + chomp $root_disk; + + # check if the found partition is a raid volume + if($root_disk =~ /\/dev\/md/) { + $root_disk = check_raid($root_disk); + } + } + + if (-b $root_disk) { + + if($root_disk =~ /$uuidpath/) { + print "$root_disk is already updated - nothing to do\n"; + } + else { + if($opt_v) { print "convert root option $root_disk into new UUID\n"; } + + $root_id = find_id_link($root_disk,$uuidpath); + if (not -l "$uuidpath/$root_id") { $exit = 1; } + } + } + else { + if($opt_v) { print "cannot read $root_disk: link does not exist!\n"; } + $exit = 1; + } + return $exit; +} + +sub find_id_link { + + my $olddev = $_[0]; + my $path_id = $_[1]; + my @sellinks; + my $_idlink; + my $_actlink; + my $newdevid = ''; + my $ok = 0; + + opendir(MYDH, "$path_id") or die("cannot open $path_id: $! \n"); + + @sellinks = grep(!/\-part\d\d?$/, grep(!/^\.\.?$/, readdir(MYDH))); + foreach $_idlink (@sellinks) { + + if(not $_idlink =~ /^usb/ and not $_idlink =~ /^scsi/ + and length($_idlink) > 10 and $ok == 0) { + + $_actlink = readlink("$path_id/$_idlink"); + $_actlink =~ s/^\.\.\/\.\.\//\/dev\//; + if($opt_v) { print "** try: $_actlink => $_idlink \n"; } + + if($_actlink eq $olddev) { + $newdevid = $_idlink; + if($opt_v) { print "** convert: $_actlink => $path_id/$_idlink \n"; } + # run only one time + $ok = 1; + } + } + } + closedir(MYDH); + + if($opt_v and not $ok) { print "$olddev not converted: link not useful\n\n"; } + + return ($newdevid); +} + +sub write_boot_option { + + my $oldline = ''; + my $comline = ''; + my $newline = ''; + my @status; + my $_preold; + my $_prenew; + + if (-f $liloconf) { + # move old lilo.conf to lilo.conf_old + @status = stat($liloconf); + move ($liloconf, $liloconfold); + utime ($status[9],$status[9],$liloconfold); + + # copy all lines from lilo.conf_old into + # new lilo.conf and add 'boot=' line + my $ok = 0; + open(MYFH_NEW, "> $liloconf") or die("cannot open $liloconf: $!"); + open(MYFH_OLD, "< $liloconfold") or die ("cannot open $liloconfold: $!"); + + while () { + # line read from MYFH_OLD + $oldline = $_; + + if (/^boot/ and $ok == 0) { + $newline = "boot = $boot_id\n"; + print MYFH_NEW "#" . $oldline; + print MYFH_NEW $newline; + if($opt_v) { print "+ #" . $oldline; } + print "+ " . $newline; + if($opt_v) { print "\n"; } + # convert only one time + $ok = 1; + } + elsif (/^#boot/ and $optboot == -1 and $ok == 0) { + # found a line with boot option commented out + $newline = "boot = $boot_id\n"; + print MYFH_NEW $oldline; + print MYFH_NEW $newline; + if($opt_v) { print "+ " . $oldline; } + print "+ " . $newline; + if($opt_v) { print "\n"; } + # convert only one time + $ok = 1; + } + elsif (/^root/ or /^\troot/) { + # found a line with root option + if (detect_root_device($oldline) == 0) { + $comline = comment_root_line($oldline); + $newline = modern_root_line($oldline,$root_id); + print MYFH_NEW $comline; + print MYFH_NEW $newline; + if($opt_v) { print '+ ' . $comline; } + print '+ ' . $newline; + if($opt_v) { print "\n"; } + } + else { + print MYFH_NEW $oldline; + } + } + else { + print MYFH_NEW $oldline; + } + } + close(MYFH_OLD); + close(MYFH_NEW); + } + else { + print "file $liloconf does not exist: nothing changed\n"; + } +} + +sub comment_root_line { + + my $rootline = $_[0]; + + if( $rootline =~ /root/) { + $rootline =~ s/root/#root/; + } + return $rootline; +} + +sub modern_root_line { + + my $oldline = $_[0]; + my $newline = $_[0]; + my $rootid = $_[1]; + my $indent = ''; + + if($oldline =~ /root/) { + $indent = $oldline; + chomp $indent; + $indent =~ s/^(\t?)root.*/$1/; + $newline = $indent . "root = \"UUID=$rootid\"\n"; + } + return $newline; +} + + +main(); + + +__END__ + + +=head1 NAME + +lilo-uuid-diskid - convert boot / root options to diskid and uuid in lilo.conf + +=head1 SYNOPSIS + +lilo-uuid-diskid [-h] [-v] [lilo.conf] + +=head1 DESCRIPTION + +This script looks for the boot block device or boot partition and create the +right diskid or uuid as boot option. Then it looks for all root partitions +and create the right uuids as root options. + +These conversions are necessary for use with newer kernel (>= 2.6.26) if it +use the libata module for parallel and serial ATA interfaces of block devices +(i. e. hard disks with IDE or SATA interface, usbsticks). + +=head1 EXAMPLES + +Lines in the configuration file /etc/lilo.conf: + + #boot = /dev/sda + boot = /dev/disk/by-id/ata-SAMSUNG_SV1604N_S01FJ10X999999 + + #root = /dev/sda1 + root = "UUID=/dev/disk/by-uuid/18843936-00f9-4df0-a373-000d05a5dd44" + +=head1 OPTIONS + +=over 4 + +=item B<-h> + +Print a brief help. + +=item B<-v> + +Print verbose messages. + +=back + +=head1 AUTHOR + +B was written by Joachim Wiedorn. + +=cut -- 2.39.2