dh-kpatches-0.99.36+nmu2/ 0000755 0000000 0000000 00000000000 10251672526 011646 5 ustar dh-kpatches-0.99.36+nmu2/dh-kpatches.nw 0000644 0000000 0000000 00000100256 10251671713 014410 0 ustar
dh-kpatches implementation
dh-kpatches implementation
@
The two Parts
The dh-kpatches system is made of two parts. The first one takes
patch descriptions, and produces kernel-patch packages; the second
one is (currently) contained in those patch packages, and handles
application of the patches to a kernel source tree, as well as
their removal.
The application/removal scripts are (currently) generated from
templates by the dh_installkpatches script for each
kernel-patch package.
Currently, the patch descriptions are completely parsed by
dh_installkpatches , and the apply/unpatch scripts are
specific to each package, and can only act on the patches
dh_installkpatches taught them about.
Packaging-time work
The dh_installkpatches helper
This is the debhelper-based script that will cause our packages
to install patches in the One True Way. Its base structure is
that of a standard debhelper script.
<>=
#!/usr/bin/perl -w
#
# dh_installkpatches $Revision: 1.17.1.4.1.24.1.5 $
#
# Reads debian/$package.kpatches[.foo], installs all files necessary
# to have make-kpkg use the kernel patches described in there.
#
# (c) 2000-2003 Yann Dirson
# Some parts based on code from Adam Di Carlo and Joey Hess
use strict;
use Debian::Debhelper::Dh_Lib;
init();
<>
PACKAGE: foreach my $package (@{$dh{DOPACKAGES}}) {
my $tmp = tmpdir($package);
my $ext = pkgext($package);
# There are two filename formats, the usual
# plus an extended format (debian/package.*).
opendir(DEB,"debian/") || error("can't read debian directory: $!");
# If this is the main package, we need to handle unprefixed filenames.
# For all packages, we must support both the usual filename format plus
# that format with a period an something appended.
my $regexp="\Q$package\E\.";
if ($package eq $dh{MAINPACKAGE}) {
$regexp="(|$regexp)";
}
my @files = grep { /^${regexp}kpatches(\..*)?$/ } readdir(DEB);
closedir(DEB);
# next package if there are no patches in there
next PACKAGE if $#files < 0;
<>
}
@
Patch processing
For each binary package, all kpatches files are processed
to generate one apply script with a single diff
operation (and its corresponding unpatch script).
<>=
<>
foreach my $file (@files) {
my %patchinfo = read_control_file ("debian/$file");
# use Data::Dumper;
# print Dumper (%patchinfo);
my $patchid = $patchinfo{general}->{'patch-id'};
# transformation of the ID to be acceptable as part of an envvar's name
$patchinfo{general}->{'clean-patch-id'} = $patchinfo{general}->{'patch-id'};
$patchinfo{general}->{'clean-patch-id'} =~ s/-/_/g;
# protect pipes and dquotes for sed command-line
$patchinfo{general}->{'patch-name'} =~ s,([|\"]),\\$1,g;
<>
}
<>
@
kpatch:depends substvar
A number of packages are needed by kernel-patch packages:
bash 2.x or better
because apply scripts use arrays
patch
because we (currently) only apply patches made of diff files
grep-dctrl
is used to register the version of the kernel-patch
package into the kernel-image package
<>=
my $pkgdeps = "bash (>= 2.0), patch, grep-dctrl";
@
The substvar code was derived from similar functionnality in dh_perl
v3.4.1. For idempotency, we first remove anything this program might
have previously added to the substvars file.
<>=
if (-e "debian/${ext}substvars") {
complex_doit("grep -v ^kpatch:Depends= debian/${ext}substvars > debian/${ext}substvars.new || true");
doit("mv", "debian/${ext}substvars.new","debian/${ext}substvars");
}
complex_doit("echo 'kpatch:Depends=$pkgdeps' >> debian/${ext}substvars");
@
We also make sure the package uses our substvar, and abort if not.
<>=
die 'debian/control must make package ' . $package . ' depend on ${kpatch:Depends}'
if system ("dpkg-gencontrol -p$package -Pdebian -O -T/dev/null -Vkpatch:Depends=KPATCHISUSED 2>/dev/null |"
. "grep -q '^Depends: .*KPATCHISUSED'") != 0;
@
Kernel-build-time work
For each v0 kpatches file, we produce an apply and an unpatch
script, necessary to work properly with make-kpkg. Those are
currently produced from templates.
Apply script
<>=
#! /bin/bash
set -e
<>
<>
DEPENDS=(#DEPENDS#)
KVERSIONS=(#KVERSIONS#)
PATCHFILES=(#PATCHFILES#)
DEBPATCHFILES=(#DEBPATCHFILES#)
STRIPLEVELS=(#STRIPLEVELS#)
<>
<>
<>
echo >&2 "START applying #PATCHID# patch (#PATCHNAME#)"
<>
<>
<>
<>
<>
echo >&2 "END applying #PATCHID# patch"
<>=
VERSION=$(grep ^VERSION Makefile 2>/dev/null | \
sed -e 's/[^0-9]*\([0-9]*\)/\1/')
PATCHLEVEL=$( grep ^PATCHLEVEL Makefile 2>/dev/null | \
sed -e 's/[^0-9]*\([0-9]*\)/\1/')
SUBLEVEL=$(grep ^SUBLEVEL Makefile 2>/dev/null | \
sed -e 's/[^0-9]*\([0-9]*\)/\1/')
EXTRAVERSION=$(grep ^EXTRAVERSION Makefile | head -1 2>/dev/null | \
sed -e 's/EXTRAVERSION =[ ]*\([^ ]*\)$/\1/')
KERNELBRANCHLET=${VERSION}.${PATCHLEVEL}.${SUBLEVEL}
KERNELRELEASE=${KERNELBRANCHLET}${EXTRAVERSION}
@
The candidates patch version for application to our kernel (eg. 2.6.11.11)
is the first of:
the version passed through the KPATCH_* mechanism
the version exactly matching the kernel (eg. 2.6.11.11)
the version of the "branchlet" used for short stable branches in the 2.6 branch (eg. 2.6.11)
the all version
<>=
IDX=
declare -i i=${#PATCHFILES[*]}-1
while [ $i -ge 0 ]
do
v=${KVERSIONS[$i]}
if [ -n "$KPATCH_#CLEANPATCHID#" -a "$v" = "$KPATCH_#CLEANPATCHID#" \
-o "$v" = "$KERNELRELEASE" \
-o "$v" = "$KERNELBRANCHLET" \
-o "$v" = all ]
then
IDX=$i
fi
i=i-1
done
<>
<>
@
If the KPATCH_* mechanism was used, we have a special error message
listing the requested version.
<>=
if [ -n "$KPATCH_#CLEANPATCHID#" -a ${KVERSIONS[$IDX]} != "$KPATCH_#CLEANPATCHID#" ]
then
echo >&2 "Requested kernel version \`$KPATCH_#CLEANPATCHID#' not found for patch #PATCHID#"
exit 1
elif [ -z "$IDX" ]
then
echo >&2 "No \"#PATCHNAME#\" patch found for kernel version $KERNELRELEASE"
exit 1
fi
@
Of special notice is the "debian" pseudo-flavour. Before the
kernel-patch-debian era, we had to check for README.Debian. Now we
must check for version.Debian.
<>=
KVERSION=${KVERSIONS[$IDX]}
STRIPLEVEL=${STRIPLEVELS[$IDX]}
if [ "${DEBPATCHFILES[$IDX]}" != '' -a \
\( -r version.Debian -o -r README.Debian \) ]
then
PATCHFILE=${DEBPATCHFILES[$IDX]}
else
PATCHFILE=${PATCHFILES[$IDX]}
fi
<>=
<>
<>
<>=
NEEDED_DEPS=
for dep in ${DEPENDS[$IDX]}
do
if [ -x ${TOPPATCHDIR}/${ARCHITECTURE}/${KERNELBRANCHLET}/apply/$dep ]
then
NEEDED_DEPS="${ARCHITECTURE}/${KERNELBRANCHLET}/apply/$dep $NEEDED_DEPS"
elif [ -x ${TOPPATCHDIR}/all/${KERNELBRANCHLET}/apply/$dep ]
then
NEEDED_DEPS="all/${KERNELBRANCHLET}/apply/$dep $NEEDED_DEPS"
elif [ -x ${TOPPATCHDIR}/${ARCHITECTURE}/apply/$dep ]
then
NEEDED_DEPS="${ARCHITECTURE}/apply/$dep $NEEDED_DEPS"
elif [ -x ${TOPPATCHDIR}/all/apply/$dep ]
then
NEEDED_DEPS="all/apply/$dep $NEEDED_DEPS"
else
echo >&2 "ERROR: Patch dependency \`$dep' not found - aborting"
echo >&2 "END applying #PATCHID# patch"
exit 1
fi
done
<>=
if [ "$NEEDED_DEPS" ]
then
echo >&2 "Ensuring the following patches are applied first: $NEEDED_DEPS"
for apply in ${NEEDED_DEPS}
do
dep=$(basename $apply)
${TOPPATCHDIR}/$apply
# check something was applied
if [ ! -f debian/APPLIED_${ARCHITECTURE}_$dep -a \
! -f debian/APPLIED_all_$dep ]
then
echo >&2 "ERROR: patch dependency did not left a patch stamp (version mismatch ?) - aborting"
echo >&2 "END applying #PATCHID# patch"
exit 1
fi
done
UNPATCHDEPS=$(echo ${NEEDED_DEPS} | sed s,/apply/,/unpatch/,g)
fi
<>=
echo >&2 "Testing whether \"#PATCHNAME#\" patch for $KVERSION applies (dry run):"
if ! [ -r $PATCHFILE ]
then
echo >&2 "\"#PATCHNAME#\" patch for $KVERSION not found"
exit 1
elif ! $DECOMPRESSOR $PATCHFILE |
patch --force --dry-run $PATCH_OPTIONS -p$STRIPLEVEL
then
echo >&2 "\"#PATCHNAME#\" patch for $KVERSION does not apply cleanly"
exit 1
fi
@
We do not use --force on second run, there should be no need for
it. If something requires interaction, it is likely there is a bug
somewhere, better catch it.
After applying the diff, we remove any empty files, so that files
"removed" by the diff are really removed. We make an exception for
./debian/ contents, and for files named APPLIED*, or else some (buggy)
stamp files may be caught too.
<>=
if ! $DECOMPRESSOR $PATCHFILE |
patch $PATCH_OPTIONS -p$STRIPLEVEL
then
# This should never happen, thanks to the dry-run
echo >&2 "ASSERTION FAILED - \"#PATCHNAME#\" patch for $KVERSION failed"
echo >&2 "END applying #PATCHID# patch"
exit 1
fi
echo >&2 "\"#PATCHNAME#\" patch for $KVERSION succeeded"
<>
@
All information necessary for unpatching is stored in a
debian/APPLIED_* file, for use by the unpatch
script.
<>=
mkdir -p debian
cat > 'debian/APPLIED_#PATCHARCH#_#PATCHID#' <>=
mkdir -p debian/image.d
PKGNAME=`dpkg -S $PATCHFILE | cut -d: -f1`
PKGVERS=`grep-dctrl -n -P $PKGNAME -s Version -X /var/lib/dpkg/status`
cat > 'debian/image.d/register-#PATCHID#' <> \${docdir}/applied-patches
EOF
chmod +x 'debian/image.d/register-#PATCHID#'
<>=
TOPPATCHDIR=/usr/src/kernel-patches
ARCHITECTURE=`dpkg --print-installation-architecture`
DECOMPRESSOR="zcat -f"
PATCH_OPTIONS="--ignore-whitespace --silent"
# This is informational only, used by lskpatches
DHPKPATCHES_VERSION=#DHKPVERS#
@
We consider it a success if the patch is already applied.
FIXME: we should make sure that the currently-applied patch is the
one that would have been applied.
<>=
[ -f debian/APPLIED_${ARCHITECTURE}_#PATCHID# -o \
-f debian/APPLIED_all_#PATCHID# ] && exit 0
@
Unpatch script
<>=
#! /bin/bash
set -e
# This "unpatch" script was automatically generated by
# dh_installkpatches from unpatch.tmpl $Revision: 1.17.1.4.1.24.1.5 $
<>
ARCHITECTURE=`dpkg --print-installation-architecture`
PATCHID=#PATCHID#
PATCHARCH=#PATCHARCH#
TOPPATCHDIR=/usr/src/kernel-patches
DECOMPRESSOR="zcat -f"
STAMP=debian/APPLIED_${PATCHARCH}_$PATCHID
PATCH_OPTIONS="--ignore-whitespace --silent"
[ -f $STAMP ] || exit 0
<>
<>
<>
<>
<>
@
<>=
if [ ! -s $STAMP ]
then
cat >&2 <>=
if [ $(echo $(wc -l < $STAMP) ) != 1 ]
then
. $STAMP
else
# old format
APPLY_INFO=$(cat $STAMP)
PATCHFILE=$(echo ${APPLY_INFO} | cut -d# -f1)
STRIPLEVEL=$(echo ${APPLY_INFO} | cut -d# -f2)
fi
@
<>=
if [ ! -r $PATCHFILE ]
then
cat >&2 <>=
if [ -n "$DEPENDS" ]
then
echo >&2 "Also un-applying the following patches: $DEPENDS"
for dep in $DEPENDS
do
if [ -x ${TOPPATCHDIR}/$dep ]
then
${TOPPATCHDIR}/$dep
else
echo >&2 "Could not unpatch dependency: $dep - stopping here."
echo >&2 "END unpatching #PATCHID# patch"
exit 1
fi
done
fi
@
<>=
if grep -l "^DEPENDS=.*[' ]#PATCHARCH#/unpatch/#PATCHID#[' ]" debian/APPLIED_* >/dev/null 2>/dev/null
then
# There are patches depending on this one, to be removed before.
# the dep will be removed by the last of those other patches.
echo >&2 "NOT unpatching \"#PATCHNAME#\" since other patches still rely on it"
exit 0
fi
@
<>=
echo >&2 "START unpatching #PATCHID# patch (#PATCHNAME#)"
$DECOMPRESSOR $PATCHFILE | patch -R -p$STRIPLEVEL $PATCH_OPTIONS
rm -f debian/APPLIED_${PATCHARCH}_$PATCHID debian/image.d/register-#PATCHID#
<>
<>
rmdir -p debian/image.d || true
echo >&2 "END unpatching #PATCHID# patch"
@
Common stuff
<>=
if ! [ -d kernel -a -d Documentation ]
then
echo >&2 "Not in kernel top level directory. Exiting"
exit 1
fi
<>=
echo >&2 "Removing empty files:"
# make an exception for ./debian, or else the stamp files will go too.
find . -path ./debian -prune -o \
-type f -size 0 ! -name 'APPLIED*' -exec rm {} \; -print
echo >&2 "Done."
@
Reading a kpatches control file
When reading a kpatches control file, we store its contents
according a data model suitable for the most recent file-format, and
will map data extracted from old file-formats into the modern one.
Generic (v1) data structures
The v1 data structures are a hash of general fields taken from the
initial stance (eg. PatchName ), a hash of default values also
taken from the initial stance, and a sequence of alternative versions
of the patch, each of which containing a sequence of operations to
apply to the kernel tree:
<>=
my %patchinfo = ('general' => {},
'defaults' => {},
'alternatives' => []);
@
We provide a single entry-point to the controlfile reader, which will
act in different ways according to the format-version.
If we have a v0 header, we migrate the relevant contents of the v0
header into the default-values section ot the [[%patchinfo]]
structure, before going on reading.
@
<>=
# Irregular kernel versions by branch, and their predecessor and successors.
# (Key is the predecessor, value is an array ref;
# contains the irregular version itself and the successor.)
my %irregular_kversions = (
# "2.6" => {
# "8" => [ "8.1", "9" ]
# }
);
# Gives back an array containing all the kernel versions
# from $branch.".".$start to $branch.".".$end (inclusive).
# Handles some irregular versions correctly, but depends on
# the monotonic numeric relation of successive versions.
sub iterate_over_kversions {
my ($branch, $start, $end) = @_;
my @ret;
my $v = $start;
while ($v <= $end) {
push @ret, $branch . "." . $v;
if (exists $irregular_kversions{$branch}->{$v}) {
if ($irregular_kversions{$branch}->{$v}[0] <= $end) {
push @ret, $branch . "." . $irregular_kversions{$branch}->{$v}[0];
$v = $irregular_kversions{$branch}->{$v}[1];
} else {
last;
}
} else {
$v++;
}
}
return @ret;
}
<>=
sub read_control_file {
my ($file) = @_;
<>
open (IN, $file) or die "cannot open $file: $!";
# read control-file header
read_control_file_section ($patchinfo{general});
if ((!defined $patchinfo{general}->{'kpatch-format-version'}) or
($patchinfo{general}->{'kpatch-format-version'} == 0)) {
$patchinfo{defaults} = control_file_v0_header_to_v1_defaults ($patchinfo{general});
<>
# } elsif ($patchinfo{general}->{'kpatch-format-version'} == 1) {
# Revision 1
# Eh, not yet :)
} else {
die "Unsupported Kpatch-format-version: \`" .
$patchinfo{general}->{'kpatch-format-version'} . "'";
}
close IN;
validate (\%patchinfo);
return %patchinfo;
}
@
Once a [[%patchinfo]] structure has been filled, we can run some
checks on it, to make as sure as possible that it is correct.
FIXME: this should do much more tests !
<>=
sub validate {
my ($patchinfo) = @_;
die "Patch-Id can only contain alphanumerics, hyphens, and underscores"
if $patchinfo->{general}->{'patch-id'} =~ /[^\w-]/;
foreach my $alternative (@{$patchinfo->{alternatives}}) {
foreach my $operation (@{$alternative->{operations}}) {
die "Diff file does not exist: " . $operation->{'diff-file'}
if ($operation->{format} eq 'diff') and ! -r $operation->{'diff-file'};
die "Diff file changes EXTRAVERSION: " . $operation->{'diff-file'}
if 0 == system ('grep -q "^-EXTRAVERSION\>" ' . $operation->{'diff-file'});
}
}
}
@
Reading a control-file section is something quite generic. Maybe
there is a generic API for doing that now ?
This function slightly adapted from code in install-docs from Adam
Di Carlo, and this is the main reason why it is not split into chunks.
<>=
sub read_control_file_section {
my ($pfields) = @_;
my $alreadyreadsomething = 0;
my ($key,$value);
while () {
chomp;
# empty line?
if (/^\s*$/o) {
if ($alreadyreadsomething) {
last;
} else {
next;
}
}
$alreadyreadsomething = 1;
if (/^(\S+)\s*:\s*(.*)$/) {
# first line of a new field
($key,$value) = (lc $1,$2);
#print STDERR "$key -> $value\n";
if (exists $pfields->{$key}) {
warn "warning: $key: overwriting previous setting of control field";
}
$pfields->{$key} = $value;
} elsif (/^\s+(\S.*)$/) {
# additional line in a multi-line field
$value = $1;
defined($key) or die "syntax error in control file: no field specified";
#print STDERR "$key -> $value (continued)\n";
$pfields->{$key} .= "\n$value";
} else {
die "syntax error in control file: $_";
}
}
return $alreadyreadsomething;
}
@
Handling v0 definitions
A v0 kpatches file is just a list of alternatives, each composed of
only one diff operation. We have to convert them into proper
structures so that the v1-based processing works as expected.
<>=
my $cfs = {};
while (read_control_file_section ($cfs)) {
push (@{$patchinfo{alternatives}},
control_file_v0_section_to_alternative($cfs));
$cfs = {};
}
@
The function that does the conversion simply maps known fields into
their final location.
<>=
sub control_file_v0_section_to_alternative {
my ($cfs) = @_;
# FIXME: should also process general section, and convert default
# values - probably in a similar function
return {
conditions => {
'kernel-version' => $cfs->{'kernel-version'},
'architecture' => $cfs->{architecture},
},
depends => $cfs->{depends},
defaults => {},
operations => [
{
'format' => 'diff',
'diff-file' => $cfs->{'patch-file'},
'debian-diff-file' => $cfs->{'debian-patch-file'},
'path-strip-level' => $cfs->{'path-strip-level'},
}
],
};
}
@
The v0 header differs from the v1 header, in that "default" entries
are implicit, and for a small well-defined set of fields. When
reading a v0 header, we have to explicit them, and strip them from the
general fields.
<>=
sub control_file_v0_header_to_v1_defaults {
my ($header) = @_;
my %defaults;
foreach my $key (keys %{$header}) {
if (! grep { $key eq $_ } ('patch-name', 'patch-id')) {
$defaults{$key} = $header->{$key};
delete $header->{$key};
}
}
return \%defaults;
}
@
Fields of kpatch files
There are 2 types of fields, denoted by constants defined the fields library . Some are mandatory, some are optional.
The optional ones can all be given a default value, but mandatory ones
cannot use this inheritance mechanism -- hence the [[$FIELD_INHERITS]]
name.
Due to this inheritance mechanism, the final value of a field has to
be computed according to given rules for inheritance and defaulting.
From text fields to data structures
Generic alternative fields
We record all archs mentionned in the kpatches file, so that we
know for which archs we have to generate the apply/unpatch scripts.
<>=
{
my @archfield =
split (/, */, field_value ($patchinfo{general}, $alternative->{conditions},
'architecture', $FIELD_INHERITS, 'all',
\%patchinfo));
$alternative->{conditions}->{architecture} = \@archfield;
foreach my $arch (@archfield) {
push @archs, $arch unless grep { $_ eq $arch } @archs;
}
}
@
The kernel version can be specified either as a single version or
as a range.
FIXME: how a is value "all" handled ? It seems filtered out by the
test below...
<>=
{
# pattern matching any kernel version (marks branch as $1 and version as $2)
my $ranged_kversion_pattern = qr/^(\d+\.\d+)\.(\d+(?:\.\d+)?)$/;
my $minimal_kversion_pattern = qr/^(\d+\.\d+)\.(\d+(?:\.\d+)?)/;
my $kversion = field_value ($patchinfo{general}, $alternative->{conditions},
'kernel-version', $FIELD_MANDATORY);
# parse "2.4.5 - 2.4.7" and "2.5.4 -" syntaxes
my @kv = split (/\s+/, $kversion);
if ($#kv > 0) {
# FIXME: validity check is really too strict, but we need a
# good kversion comparison algorithm to attempt any better
# (ie. "-pre" and "-test" at least are special)
$kv[0] =~ $ranged_kversion_pattern or die "Malformed kernel version: `$kv[0]'";
my ($branch, $first) = ($1, $2);
die "Malformed kernel-version range \`$kversion'"
unless ($kv[1] eq '-') && ($#kv <= 2);
if ($#kv == 1) {
die "Unbounded ranges not supported yet: \`$kversion'";
$kversion = [ $branch, $first ];
} else {
$kv[2] =~ $ranged_kversion_pattern or die "Malformed kernel version: `$kv[2]'";
die "Cross-branch ranges are not allowed: `$kversion'"
unless $1 == $branch;
die "Reverse-ordered range: `$kversion'" if $2 < $first;
$kversion = [ $branch, $first, $2 ];
}
} else {
$kv[0] =~ $minimal_kversion_pattern or die "Malformed kernel version: `$kv[0]'";
}
$alternative->{conditions}->{'kernel-version'} = $kversion;
}
@
Depends is a comma- and space-separated list, and will be
used in the bash apply script to initialize an array, so must be made
space-separated only.
<>=
$alternative->{depends} = field_value ($patchinfo{general}, $alternative,
'depends', $FIELD_INHERITS, "",
\%patchinfo);
$alternative->{depends} =~ s/, */ /g;
@
Per-operation fields
This is simplest of all fields, nothing special is done apart from
memorizing it.
<>=
$op->{'path-strip-level'} = field_value ($patchinfo{general}, $op,
'path-strip-level', $FIELD_INHERITS, 1,
$alternative, \%patchinfo);
@
Since the diff files may be compressed, we are only recording here
their location in the source tree, and we are delaying the recording of
their final filename until they are installed and maybe compressed.
This will be done as we [[<>]].
<>=
$op->{'diff-file'} = field_value ($patchinfo{general}, $op,
'diff-file', $FIELD_MANDATORY);
$op->{'debian-diff-file'} = field_value ($patchinfo{general}, $op,
'debian-diff-file', $FIELD_INHERITS);
@
Field-handling library
Field inheritance
<>=
my $FIELD_MANDATORY = 0;
my $FIELD_INHERITS = 1;
@
[[$inherits]] should have one of the values defined above.
[[$default]] can be [[undef]] when there is no default value for the
field.
<>=
sub field_value {
my ($general, $hash, $name, $inherits, $default, @defaultlists) = @_;
my $value = $hash->{$name};
if ($inherits == $FIELD_MANDATORY) {
die "Patchfile info lacks $name field" unless defined $value;
}
# first go through explicit default values
foreach my $defaultlist (@defaultlists) {
$value = $defaultlist->{defaults}->{$name} unless defined $value;
}
# then use hardcoded default as a fallback
if (defined $default) {
$value = $default unless defined $value;
}
return $value;
}
@
Recording a patchfile field for later use
We use hashes to store sequences of values for each arch. These
sequences of values will be directly used to produce the apply/unpatch
scripts from their templates.
<>=
# records a field value for a given patchfile on a given arch
sub record_patchfile_field {
my ($hash, $arch, $value) = @_;
if (defined $hash->{$arch}) {
$hash->{$arch} .= " $value";
} else {
$hash->{$arch} = "$value";
}
}
@
Patch processing
In a single apply script, all alternatives are handled,
and the one to use will be determined at runtime.
We currently support only one operation per alternative (v0
format), and a great deal of this restriction lies in this part, so I
will not spend to much time structuring this part, until things are
properly implemented.
To get proper v1 support we will put everything including kpatches
file parsing into a generic apply script, and have patch packages only
symlink to this one.
<>=
my %kversions=();
my %patchfiles=();
my %debpatchfiles=();
my %striplevels=();
my %depends=();
my @archs=();
# put the right files in the right places
foreach my $alternative (@{$patchinfo{alternatives}}) {
my $op = $alternative->{operations}->[0];
<>
<>
<>
}
<>
@
For each alternative, we compute the value to use for each field,
possibly using a default value if none was provided, and in some cases
splitting into an array. The final value is stored in the place of
the original one.
Diff files thus identified are then installed, and entries for the
diff files are then recorded for use when generating the apply/unpatch
scripts for each of the named architectures.
There is no particular ordering required between the computation of
the various fields, but to help moving towards v1 format, we group
them by first handling those specific to the alternative itself, and
then those specific to the single diff operation in this alternative.
<>=
<>
<>
<>
<>
<>
@
All diff files are now located under a single
/usr/src/kernel-patches/diffs/ tree.
<>=
my $srcdir = "/usr/src/kernel-patches/diffs/$patchid";
doit ("mkdir", "-p", "$tmp$srcdir") unless -d "$tmp$srcdir";
$op->{'installed-diff-file'} = "$srcdir/" . basename($op->{'diff-file'});
doit ("cp", $op->{'diff-file'}, "$tmp$op->{'installed-diff-file'}");
doit ("gzip", "-9fq", "$tmp$op->{'installed-diff-file'}");
$op->{'installed-diff-file'} = "$op->{'installed-diff-file'}.gz"
if -r "$tmp$op->{'installed-diff-file'}.gz";
if (defined $op->{'debian-diff-file'}) {
$op->{'installed-debian-diff-file'} = "$srcdir/" . basename($op->{'debian-diff-file'});
doit ("cp", $op->{'debian-diff-file'}, "$tmp$op->{'installed-debian-diff-file'}");
doit ("gzip", "-9fq", "$tmp$op->{'installed-debian-diff-file'}");
$op->{'installed-debian-diff-file'} = "$op->{'installed-debian-diff-file'}.gz"
if -r "$tmp$op->{'installed-debian-diff-file'}.gz";
} else {
$op->{'installed-debian-diff-file'} = '';
}
@
Version ranges are currently emulated, by duplicating the entry for
each integer kernel revision in the range.
This is a temporary behaviour, which does not allow pre-release kernel
versions to be seen as part of the range. Adequate version-comparison
function and data-structures will be used instead, when time permits.
<>=
foreach my $arch (@{$alternative->{conditions}->{architecture}}) {
if ((ref $alternative->{conditions}->{'kernel-version'}) eq 'ARRAY') {
my @kernel_version = @{$alternative->{conditions}->{'kernel-version'}};
foreach my $version (iterate_over_kversions($kernel_version[0], $kernel_version[1], $kernel_version[2])) {
record_patchfile_field (\%kversions, $arch, $version);
record_patchfile_field (\%striplevels, $arch, $op->{'path-strip-level'});
record_patchfile_field (\%depends, $arch, '"' . $alternative->{depends} . '"');
record_patchfile_field (\%patchfiles, $arch, '"' . $op->{'installed-diff-file'} . '"');
record_patchfile_field (\%debpatchfiles, $arch, '"' . $op->{'installed-debian-diff-file'} . '"');
}
} else {
record_patchfile_field (\%kversions, $arch,
$alternative->{conditions}->{'kernel-version'});
record_patchfile_field (\%striplevels, $arch, $op->{'path-strip-level'});
record_patchfile_field (\%depends, $arch, '"' . $alternative->{depends} . '"');
record_patchfile_field (\%patchfiles, $arch, '"' . $op->{'installed-diff-file'} . '"');
record_patchfile_field (\%debpatchfiles, $arch, '"' . $op->{'installed-debian-diff-file'} . '"');
}
}
@
apply and unpatch are currently generated from
templates, by substituting in there the values computed from the patch
definition expressed in the kpatches file.
<>=
foreach my $arch (@archs) {
my $pdir = "/usr/src/kernel-patches/$arch";
foreach my $script ('apply', 'unpatch') {
doit ("mkdir", "-p", "$tmp$pdir/$script");
complex_doit ('sed < @TMPLDIR@/' . "$script.tmpl >$tmp$pdir/$script/$patchid" .
' -e \'s/#PATCHID#/' . $patchinfo{general}->{'patch-id'} . '/g\'' .
' -e \'s/#CLEANPATCHID#/' . $patchinfo{general}->{'clean-patch-id'} . '/g\'' .
' -e \'s|#PATCHNAME#|' . $patchinfo{general}->{'patch-name'} . '|g\'' .
" -e 's/#DHKPVERS#/@DHKPVERS@/g'" .
" -e 's,#TMPLDIR#,@TMPLDIR@,g'" .
" -e 's/#DEPENDS#/$depends{$arch}/g'" .
" -e 's/#KVERSIONS#/$kversions{$arch}/g'" .
" -e 's|#PATCHFILES#|$patchfiles{$arch}|g'" .
" -e 's|#DEBPATCHFILES#|$debpatchfiles{$arch}|g'" .
" -e 's/#PATCHARCH#/$arch/g'" .
" -e 's/#STRIPLEVELS#/$striplevels{$arch}/g'"
);
doit ("chmod", "0755", "$tmp$pdir/$script/$patchid");
doit ("mkdir", "-p", "$tmp/usr/share/doc/$package");
doit ('cp',
'@TMPLDIR@/README-kernelpatch.Debian',
"$tmp/usr/share/doc/$package/");
}
}
@
Index of chunks
@
dh-kpatches-0.99.36+nmu2/lskpatches 0000755 0000000 0000000 00000003333 07627000125 013730 0 ustar #! /bin/bash
set -e
KPATCHDIR=/usr/src/kernel-patches
FORMAT='%-20s%-10s%-10s%-12s%s\n'
ARCH=$(dpkg-architecture -qDEB_HOST_ARCH)
DIRS_ALL_ALL=$(ls -d ${KPATCHDIR}/all/apply 2>/dev/null || true)
DIRS_ARCH_ALL=$(ls -d ${KPATCHDIR}/*/apply 2>/dev/null | grep -v "^${KPATCHDIR}/all/" || true)
DIRS_ALL_VERS=$(ls -d ${KPATCHDIR}/all/*/apply 2>/dev/null || true)
DIRS_ARCH_VERS=$(ls -d ${KPATCHDIR}/*/*/apply 2>/dev/null | grep -v "^${KPATCHDIR}/all/" || true)
# Note: additional "echo $()" calls used to strip spurious spaces
dhkp_kversions()
{
echo $(grep ^KVERSIONS $1 | sed 's/^.*(\(.*\))$/\1/')
}
dhkp_version()
{
local rcs=$(echo $(grep -F 'apply.tmpl $''Revision:' $1 | cut -d'$' -f2 | cut -d: -f2))
local dhkp=$(grep ^DHPKPATCHES_VERSION= $1 | cut -d= -f2)
if [ -n "${dhkp}" ]
then
# post-woody
echo ${dhkp}
elif [ -n "${rcs}" ]
then
# woody era
echo "RCS ${rcs}"
else
echo ''
fi
}
format()
{
printf ${FORMAT} "$1" "$2" "$3" "$(dhkp_version $1)" "$(dhkp_kversions $1)"
}
# Header
printf ${FORMAT} PatchID Arch KVers dhkpVers dhkp-KVers
for dir in ${DIRS_ALL_ALL}
do
(
cd ${dir}
for kp in $(ls)
do
format ${kp} 'all' 'all'
done
)
done
for dir in ${DIRS_ARCH_ALL}
do
(
arch=$(basename $(dirname ${dir}))
cd ${dir}
for kp in $(ls)
do
format ${kp} ${arch} 'all'
done
)
done
for dir in ${DIRS_ALL_VERS}
do
(
vers=$(basename $(dirname ${dir}))
cd ${dir}
for kp in $(ls)
do
format ${kp} 'all' ${vers}
done
)
done
for dir in ${DIRS_ARCH_VERS}
do
(
vers=$(basename $(dirname ${dir}))
arch=$(basename $(dirname $(dirname ${dir})))
cd ${dir}
for kp in $(ls)
do
format ${kp} ${arch} ${vers}
done
)
done
dh-kpatches-0.99.36+nmu2/dh-kpatches.prj 0000644 0000000 0000000 00000012725 10251672506 014563 0 ustar ;; -*- Prcs -*-
(Created-By-Prcs-Version 1 3 3)
(Project-Description "")
(Project-Version dh-kpatches v0-maint 59)
(Parent-Version dh-kpatches v0-maint 58)
(Version-Log "typo in previous checkin
ignore stderr lines from dpkg-gencontrol (#263617)
")
(New-Version-Log "")
(Checkin-Time "Thu, 09 Jun 2005 00:46:30 +0200")
(Checkin-Login dwitch)
(Populate-Ignore ("RCS/.*,v$"
"^debian/tmp"
"^debian/dh-kpatches/"
"^debian/kernel-patch-scripts"
".*-stamp$"
"^debian/.*substvars$"
"^debian/.*.debhelper$"
"^dh_installkpatches.in$"
"^doc/dh-kpatches.log$"
"^dh_installkpatches$"
"^doc/lskpatches.1$"
"^doc/dh-kpatches.html$"
"^doc/manpage.refs$"
"^doc/manpage.links$"
"^doc/dh-kpatches.out$"
"^debian/files$"
"^doc/dh-kpatches.jtex$"
"^doc/dh-kpatches.aux$"
"^doc/dh-kpatches.pdf$"
"^doc/dh_installkpatches.1$"
"^dh-kpatches-html/" "^dh-kpatches.html"
"^dh-kpatches.latex$"
"^dh-kpatches.ps$"
"^dh-kpatches.dvi$"
"^dh-kpatches.aux$"
"^dh-kpatches.log$"
))
(Project-Keywords)
(Files
;; This is a comment. Fill in files here.
;; For example: (prcs/checkout.cc ())
;; Files added by populate at Sat, 15 Feb 2003 20:44:20 +0100,
;; to version 0.0(w), by dwitch:
(examples/kernel-patch-kdb.kpatches.arch (dh-kpatches/0_kdb-1.6.kp 1.2 644))
(doc/dh_installkpatches.refentry-contents.sgml (dh-kpatches/1_dh_install 1.9 644))
(doc/kpatch-policy.debiandoc.sgml (dh-kpatches/2_kpatch-pol 1.2 444))
(Makefile (dh-kpatches/3_Makefile 1.17 644))
(dh-kpatches.nw (dh-kpatches/4_dh_install 1.17.1.4.1.24.1.9 644))
(doc/dh-kpatches.docbook.sgml (dh-kpatches/5_kpatches-s 1.14 644))
(debian/rules (dh-kpatches/8_rules 1.8 755))
(debian/control (dh-kpatches/9_control 1.14 644))
(debian/copyright (dh-kpatches/12_copyright 1.2 644))
(debian/changelog (dh-kpatches/13_changelog 1.25.1.23.1.11.1.8 644))
;; Files deleted by populate at Sat, 15 Feb 2003 20:48:01 +0100,
;; from version release-0.1(w), by dwitch:
; (debian/README.Debian ())
;; Files added by populate at Sat, 15 Feb 2003 23:36:32 +0100,
;; to version release-0.3(w), by dwitch:
(TODO (dh-kpatches/14_TODO 1.18 644))
;; Files added by populate at Sat, 15 Feb 2003 23:38:41 +0100,
;; to version release-0.6(w), by dwitch:
(debian/dh-kpatches.overrides (dh-kpatches/15_overrides 1.1 644))
;; Files added by populate at Sat, 15 Feb 2003 23:45:55 +0100,
;; to version release-0.7(w), by dwitch:
(examples/kernel-patch-kdb.kpatches.common (dh-kpatches/17_kernel-pat 1.1 644))
(debian/README-kernelpatch (dh-kpatches/18_README-ker 1.3 644))
;; Files added by populate at Sat, 15 Feb 2003 23:57:04 +0100,
;; to version release-0.99.4(w), by dwitch:
(doc/dh_installkpatches.refentry.sgml (dh-kpatches/19_dh_install 1.1 644))
(doc/Makefile (dh-kpatches/20_Makefile 1.8 644))
(debian/dh-kpatches.doc-base.dh-kpatches (dh-kpatches/21_dh-kpatche 1.2 644))
;; Files deleted by populate at Sat, 15 Feb 2003 23:57:04 +0100,
;; from version release-0.99.4(w), by dwitch:
; (dh_installkpatches.xml ())
;; Files added by populate at Sun, 16 Feb 2003 00:02:01 +0100,
;; to version release-0.99.10(w), by dwitch:
(lskpatches (dh-kpatches/23_lskpatches 1.3 755))
(doc/lskpatches.refentry.sgml (dh-kpatches/24_lskpatches 1.1 644))
(doc/jadetex.cfg (dh-kpatches/25_jadetex.cf 1.1 644))
(debian/dh-kpatches.files (dh-kpatches/26_dh-kpatche 1.2 644))
(debian/kernel-patch-scripts.files (dh-kpatches/27_kernel-pat 1.3 644))
(debian/compat (dh-kpatches/28_compat 1.1 644))
;; Files added by populate at Sun, 16 Feb 2003 00:03:31 +0100,
;; to version release-0.99.11(w), by dwitch:
(examples-v1/kernel-patch-lkcd-alt-expanded.kpatches (dh-kpatches/29_kernel-pat 1.1 644))
(examples-v1/kernel-patch-lkcd-alt.kpatches (dh-kpatches/30_kernel-pat 1.1 644))
(examples-v1/kernel-patch-lkcd.kpatches (dh-kpatches/31_kernel-pat 1.1 644))
(examples-v1/kernel-patch-ltt.kpatches (dh-kpatches/32_kernel-pat 1.1 644))
;; Files deleted by populate at Sun, 16 Feb 2003 00:03:31 +0100,
;; from version release-0.99.11(w), by dwitch:
; (dh-kpatches.prj.bak ())
;; Files added by populate at Sun, 16 Feb 2003 00:04:40 +0100,
;; to version release-0.99.12(w), by dwitch:
(register-patch (dh-kpatches/33_register-p 1.4 644))
;; Files added by populate at Sun, 16 Feb 2003 00:07:40 +0100,
;; to version release-0.99.13(w), by dwitch:
(examples-v1/kernel-patch-lkcd-alt3.kpatches (dh-kpatches/34_kernel-pat 1.1 644))
(debian/kernel-patch-scripts.overrides (dh-kpatches/35_kernel-pat 1.1 644))
;; Files deleted by depopulate at Wed, 26 Feb 2003 00:16:09 +0100,
;; from version v0-maint.6(w), by dwitch:
; (debian/dh-kpatches.doc-base.kpatch-policy ())
;; Files added by populate at Sun, 16 Nov 2003 00:45:42 +0100,
;; to version v0-dev-noweb.9(w), by dwitch:
(noweb.css (dh-kpatches/40_noweb.css 1.5 644))
(dh-kpatches.book (dh-kpatches/41_dh-kpatche 1.1 644))
;; Files added by populate at Sat, 22 Nov 2003 22:35:55 +0100,
;; to version v0-maint.33(w), by dwitch:
(debian/README (dh-kpatches/42_README 1.1 644))
;; Files deleted by depopulate at Sat, 29 Nov 2003 22:00:33 +0100,
;; from version v0-maint.40(w), by dwitch:
; (apply.tmpl ())
; (unpatch.tmpl ())
)
(Merge-Parents)
(New-Merge-Parents)
dh-kpatches-0.99.36+nmu2/noweb.css 0000644 0000000 0000000 00000002330 07765436357 013510 0 ustar # Stylesheet for noweb-generated HTML.
# Disclaimers:
# - I'm not a CSS expert, any visual improvements are welcome
# - This stylesheet was only tested on galeon 1.2.5 and mozilla-firebird 0.7
# - The generated contents (*:before) is completely untested, ignored
# by all tested browsers
body { background-color: white; color: black }
div.title { text-align: center; font-weight: bold; font-size: xx-large;
text-decoration: underline }
pre { background-color: lightgray; border-style: groove; font-size: larger;
margin-left: 2ex; margin-top: 1ex }
dfn { font-weight: bolder; background-color: lightyellow; font-size: larger;
border-style: ridge; border-style: ridge; border-color: lightyellow;
margin-left: -2ex; margin-top: -1ex;
text-decoration: none }
h2:before {
content: counter(h2) ". ";
counter-increment: h2;
counter-reset: h3;
}
h3:before {
content: counter(h2) "." counter(h3) ". ";
counter-increment: h3;
counter-reset: h4;
}
h4:before {
content: counter(h2) "." counter(h3) "." counter(h4) ". ";
counter-increment: h4;
counter-reset: h5;
}
dh-kpatches-0.99.36+nmu2/Makefile 0000644 0000000 0000000 00000002715 07762204674 013323 0 ustar DESTDIR =
prefix = /usr
bindir = ${prefix}/bin
datadir = ${prefix}/share/debhelper/dh-kpatches
docdir = ${prefix}/share/doc/dh-kpatches
mandir = ${prefix}/share/man
man1dir = ${mandir}/man1
DHSCRIPT = dh_installkpatches
OTHERSCRIPTS = lskpatches
TEMPLATES = apply.tmpl unpatch.tmpl register-patch
VERSION = $(shell dpkg-parsechangelog | grep ^Version: | cut -d' ' -f2)
NOWEBSRC = dh-kpatches.nw
NOWEBOUTSRC = $(shell noroots ${NOWEBSRC} | sed 's/<<\(.*\)>>/\1/')
all: ${DHSCRIPT} ${TEMPLATES}
make -C doc all
${DHSCRIPT}: ${DHSCRIPT}.in
sed -e s=@TMPLDIR@=${datadir}= -e s=@DHKPVERS@=${VERSION}=<$< >$@
chmod 755 $@
internals: ${NOWEBSRC:.nw=.ps} ${NOWEBSRC:.nw=.html}
${NOWEBOUTSRC}: % : ${NOWEBSRC}
notangle -R$@ $< | cpif $@
%.html: %.nw
noweave -html -delay \
-filter "noweb/guesslang ${NOWEBOUTSRC} | noweb/inheritlang" \
-filter "noweb/htmltoc | noweb/enscript-html --color" \
-x \
$< > $@
%.ps: dh-kpatches.book %.html
htmldoc --batch $< || test $$? = 4
clean:
rm -f ${DHSCRIPT} ${NOWEBOUTSRC}
rm -rf ${NOWEBSRC:.nw=-html}
rm -f *.aux *.log *.dvi *.ps *.latex
make -C doc clean
install: all
install -m755 -d ${DESTDIR}${datadir} ${DESTDIR}${bindir}
install -m755 ${DHSCRIPT} ${OTHERSCRIPTS} ${DESTDIR}${bindir}
install -m644 ${TEMPLATES} ${DESTDIR}${datadir}
make -C doc install
uninstall:
rm -f ${DESTDIR}${bindir}/${DHSCRIPT}
-cd ${DESTDIR}${bindir} && rm -f ${OTHERSCRIPTS}
rm -rf ${DESTDIR}${datadir}
make -C doc uninstall
dh-kpatches-0.99.36+nmu2/noweb 0000777 0000000 0000000 00000000000 07756241224 017535 2../../litprog/noweb/ydirson ustar dh-kpatches-0.99.36+nmu2/TODO 0000644 0000000 0000000 00000005303 07762221444 012341 0 ustar TODO list for 1.0 target
========================
Those will be implemented in 0.100.x, and 0.99.x will not see any new
developments, only bugfixes.
* dependency handling
- when a patch version is selected through the environment, propagate
it to dependencies to be applied (unless env was used for the dep),
and maybe check deps that were already applied.
* core v1 functionality
- complete transition of internal data structures to v1:
- modularisation of operations
- generalize apply/unpatch scripts and put them in
kernel-patch-scripts package, for space-saving and to allow
collaborating packages (see #118122), so that kpatch packages need
only install symlinks to them. But above all, this is on one of the
path to v1 implementation, so ...
- rewrite apply/unpatch in perl, since the code of those will be
mixed with the current dh_installkpatches script, to reach the above
point.
- support other operations than "diff application", esp. combined
diff+cp (#118232, #129459) - be careful on unpatch (see description of
"revision 1" format in the doc).
- support kernel flavours (see description of "revision 1" format in
the doc).
* sanity stuff
- review the kpatches-specs and kpatch-policy documents, and manpage.
- maybe make dh_inst check build-deps versionning
- make dh_installkpatches validate the fields in the kpatches file, so
that wished features do not get reported as bugs :)
(possibly) post-1.0 TODO list
=============================
- generate a ${Kernel:versions} substvar, to make it possible to
automagically maintain a useful package description.
- provide a way to hide patches that are not meant to be used
directly, but only depended upon (eg. kdbcore, evms-*), so that they
do not uselessly cripple lskpatches output by default (possibly
applies to the contents of applied-patches list as well).
- provide a make-kpatch-pkg tool to help users in building Q&D kpatch
packages for their internal use (I was not sure it was worth doing it,
but at least one make-kpkg user requested the feature)
- provide a dh_make template for helping to build official patch
packages
- tarfile support may require pax(1) to get Path-strip-level support
- support for use of make-kpkg's versionning (eg. Version-sensitive:
yes) ?
- support for open kversion ranges, and enumerated. Something like:
Kernel-version: 2.4.15 - (meaning: all 2.4 kernels starting at .15)
Kernel-version: 2.2.10 -, 2.4.5 -
Kernel-version: 2.4 (meaning: all versions in the 2.4 era)
That will require sophisticated version-comparison rules, to
accomodate well-known EXTRAVERSION prefixes (yes, upsteam-shipped
EXTRAVERSION is the prefix of the suffix ;), ie. "test" and "pre"
(-ac, -aa, -dj and such are better seen as flavours)
dh-kpatches-0.99.36+nmu2/dh-kpatches.book 0000644 0000000 0000000 00000001012 07755534061 014715 0 ustar #HTMLDOC 1.8.23
-t ps2 -f dh-kpatches.ps --book --toclevels 3 --numbered --toctitle "Table of Contents" --title --linkstyle underline --size A4 --left 1.00in --right 0.50in --top 0.50in --bottom 0.50in --header t.h --footer D.1 --nup 1 --tocheader t.h --tocfooter D.i --portrait --color --no-pscommands --no-xrxcomments --compression=1 --jpeg=0 --fontsize 11.0 --fontspacing 1.2 --headingfont Helvetica --bodyfont Times --headfootsize 11.0 --headfootfont Helvetica --charset iso-8859-1 --browserwidth 680
dh-kpatches.html
dh-kpatches-0.99.36+nmu2/doc/ 0000755 0000000 0000000 00000000000 12641300764 012410 5 ustar dh-kpatches-0.99.36+nmu2/doc/dh_installkpatches.refentry.sgml 0000644 0000000 0000000 00000000423 07623542725 021005 0 ustar
]>
&contents;
dh-kpatches-0.99.36+nmu2/doc/dh_installkpatches.refentry-contents.sgml 0000644 0000000 0000000 00000006300 07623544255 022640 0 ustar
dh_installkpatches
1
dh_installkpatches
install kernel patch into package build directories>
dh_installkpatches
debhelper options
Description
dh_installkpatches> is a debhelper script that reads
debian/package>.kpatches> or
debian/package>.kpatches.something>
files describing one or several revisions of a single kernel
patch, and installs them into the package build directory with
customized apply> and unpatch>
scripts.
It also sets the kpatch:Depends> substitution
variable, that you should use in your control file to ensure that
generated material in your package get all their dependencies.
The use of kpatch:Depends> requires a build-dependency
on version 0.99.3 or later of the dh-kpatches>
package. Using this variable is now required, since 0.99.16
(mostly because too many people forgot to set it).
Options
This program does not take any particular option in addition
to the standard
debhelper>1>
ones.
See also
debhelper>1> ,
make-kpkg>1> .
/usr/share/doc/dh-kpatches/dh-kpatches.html> or
/usr/share/doc/dh-kpatches/dh-kpatches.pdf.gz>.
Author
This tool and manual page were written by Yann Dirson
dirson@debian.org>.
Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free
Documentation License, Version 1.1 published by the Free Software
Foundation; with no Invariant Sections, no Front-Cover Texts and
no Back-Cover Texts. A copy of the license can be found under
/usr/share/common-licenses/FDL .
dh-kpatches-0.99.36+nmu2/doc/kpatch-policy.debiandoc.sgml 0000644 0000000 0000000 00000024222 07623541520 017755 0 ustar
Kernel-patch sub-policy draft document
Yann Dirson
dirson@debian.org
$Revision: 1.2 $
This document is an attempt to gather current Best
Practice(tm) in providing kernel-patches for easy use with
kernel-package (see ). It comes from the various issues that stopped me while
I started to package kernel patches, and is targetted at maintainers
of kernel-patch packages, to gain in consistency, functionality, and
smooth system integration. The intention is that at least part of it
gets some day blessed into Policy, and most of the remaining into
Packaging Manual.
This document is covered by the GNU
GPL.
Big picture summary
This section is meant to give a brief overview of how
make-kpkg works with respect to patch handling. For more
details please refer to the
manpage.
Using make-kpkg to build patched kernels
The default configuration of make-kpkg is to
ignore any available patches and build a package with whatever kernel
source is in the current directory. You can tell it to use patches
from under /usr/src/kernel-patches/ , either by setting
the PATCH_THE_KERNEL environment variable to YES
You may also set the patch_the_kernel variable in
/etc/kernel-pkg.conf , but I discourage this, you may well
forget you have this set one day. .
When asked to apply patches, make-kpkg will
apply all patches it finds for the current architecture and version
for the kernel being built. You may want to only select some of them
using the --added_patches option.
How make-kpkg applies patches
It looks for apply scripts in the
following subdirectories of /usr/src/kernel-patches/ :
-
$ARCH/$VERSION/apply/
-
$ARCH/apply/
-
all/$VERSION/apply/
-
all/apply/
At the time it will want to remove those patches, it will
then look into similar directories with name unpatch .
Typically the main job of these scripts is to apply a diff,
but well, they are scripts after all, and more complex tasks in need
of something more smart than patch may make use of this
power.
Patch scope
This section should describe possible scopes for a patch in
terms of kernel architecture and versions, and what actions to take
depending on effective scope.
As you may infer from the previous chapter, some patches are
fully generic, whereas others only apply to specific kernel versions
and/or specific architectures.
Architecture
Some patches do not include support for some achitectures,
in which case all they can bring to other architectures is to break
them in one way or another. Then they need to be restricted into
architecture-dependant directories. In the case where a patch applies
to several architectures, shared files should be hard-linked to avoid
wasting disk space.
Only patches with (at least theoretical) support for all
architectures, and non-architecture-dependant patches, belong to the
all category.
Version
Usually patches are made of a diff file. These diff files
are usually built by comparing a specific kernel-source tree and a
modified tree. Although those diffs are guaranted to apply on a tree
identical to the one which served as reference when the diff was
built, they may also apply (in the mechanical meaning defined by
patch returning success) to a number of kernel revisions
(or kernels with other patches already applied), if the areas touched
by the patch are similar enough to those in the reference tree. This
means that a patch against revision x.y.z may also apply to
x.y.(z-2) or x.y.(z+5) without patch
complaining.
However, this mechanical meaning of a patch applying is not
enough in some cases, where changes in one area may interfere with
changes in another. Such interferences will range from kernel not
being able to compile (eg. because of struct members renamed or
previously exported functions marked static) to kernels behaving in
really strange unforeseen ways, possibly causing data corruption or
all other types of behaviour you usually want to run away from.
For these reasons, depending on how tricky a patch is, one
may want to limit the range of kernel versions on which it is to be
applied. For this the version-specific subdirectories of
/usr/src/kernel-patches/ have been created. But beware
not to be too limitative, a patch against the latest stable kernel may
well be useful with the next yet-unreleased one, and you may not want
to be totalitarian with your package's users. Up to you to make a
"good choice", whatever that means.
Scripts naming and behaviour
This section is meant to give guidelines for writing the
apply and unpatch in a way that will work
securely (ie. doesn't break the current kernel-source tree), and will
integrate smoothly with the remaining of the system.
This is where currently packaged patches tend to behave in
unwanted ways.
Naming
Unless specific patches are requested, scripts in the
apply and unpatch dirs are executed via
run-parts , which runs them in lexical sort order.
It may be nice at some time to allow the names of applied patches to
make their way to the EXTRAVERSION field in the kernel revision, so
that we get kernel versions like "2.2.17+ide+ltt+int", that would
automagically provide at the same time instant information for what
patches were applied, and the ability of also installing at the same
time plain "2.2.17" as well as "2.2.17+kdb+reiserfs" (no offense to
reiserfs meant ;). It may be nice at this time to have patches
provide such a short name to make-kpkg .
Behaviour
Most of the scripts share a number of behaviours that help
them to acomplish the task that justifies their existence.
However, probably for lack of such a document, they are currently
built on an ad-hoc basis, starting with a copy of existing scripts.
I'll try here to list those behaviours and give guidelines so that
they indeed do not interfere with each other.
As of now, I don't think a single patch package (including
mines) behaves correctly in all these areas. I have started a
debhelper -like script to help in this area and to
provide a couple additional functionalities. Those interested will
find it at
apply telling unpatch the
patch was applied
This is usually done by creating a file named
debian-patches/APPLIED_patchname , which
unpatch checks to know whether it has something to do,
and which apply also checks to not try to re-apply itself.
Some patches create this file in the debian/
subdirectory, and some other patches create it at the top-level of the
kernel sources. The former causes interferences between
make-kpkg clean operation and patches applied by running
apply scripts by hand; the latter causes problems because
some apply scripts remove empty files after patching.
Further more, these files are debian-specific, so they may be better
in debian-specific subdir anyway.
Removing empty files after patching
This is mostly done to cleanup the source tree in cases
where files were suppressed or moved. Most package just run
find on the whole source tree to find them, then remove
them, and create an empty APPLIED_whatever as
described above... which gets happily removed by the next
apply script that gets run.
For good interaction between those 2 behaviours, no empty
files should be removed from the debian/ subdirectory -
anyway no file there should be removed by any patch I can think of, as
this dir is not part of an official kernel tree. This will allow
APPLIED_whatever scripts conforming to the
previous point to survive to play their role in the whole picture.
Checking whether to apply the patch
apply scripts, when they determine with
whatever means that they should not attempt to apply, should not
return an error code. This allows unversionned patches to be applied
as long as patch can do the job, without preventing other
patches to apply on versions of the kernel on which they don't
themselves apply.
Not breaking the source tree
The scripts should make sure they won't break the user's
tree, by using patch --dry-run before they really apply
the patch. Not only does this allow unversionned patches to exist at all
without enforcing version tests in the scripts, but it also allows the
user to experiment with stacking patches without having to restart
from unpacking the source at each failure.
Packaging issues
whether to include several patches per package
how to name patch packages
dh-kpatches-0.99.36+nmu2/doc/Makefile 0000644 0000000 0000000 00000002466 12641300731 014052 0 ustar DESTDIR =
prefix = /usr
docdir = ${prefix}/share/doc/dh-kpatches
mandir = ${prefix}/share/man
man1dir = ${mandir}/man1
MANPAGES = dh_installkpatches.1 lskpatches.1
POLICY = kpatch-policy.sgml
PROCESSEDPOLICIES = ${POLICY:.sgml=.txt} ${POLICY:.sgml=.html}
# debiandoc2* attempts to do something nasty with locale set
export LC_ALL=C
all: ${MANPAGES} dh-kpatches
policy: ${PROCESSEDPOLICIES}
dh-kpatches: dh-kpatches.pdf dh-kpatches.html
dh-kpatches.pdf dh-kpatches.html: dh_installkpatches.refentry-contents.sgml
clean:
rm -f ${MANPAGES} ${POLICY:.sgml=.txt} \
manpage.refs manpage.links \
*.jtex *.fot *.aux *.log *.out *.ps *.pdf
rm -rf *.html
install: all
install -m755 -d ${DESTDIR}${man1dir}
install -m644 ${MANPAGES} ${DESTDIR}${man1dir}
install -m755 -d ${DESTDIR}${docdir}
install -m644 dh-kpatches.pdf dh-kpatches.html ${DESTDIR}${docdir}
uninstall:
rm -rf ${DESTDIR}${docdir}
cd ${DESTDIR}${man1dir} && rm -f ${MANPAGES}
%.txt: %.debiandoc.sgml
debiandoc2text $<
mv ${<:.sgml=.txt} $@
%.html: %.debiandoc.sgml
debiandoc2html $<
mv ${<:.sgml=.html} $@
%.1: %.refentry.sgml
docbook2man $<
%.html: %.docbook.sgml
docbook-2-html --dssslproc openjade -s gtk -O -Vnochunks -O -Vonechunk $< >$@
rmdir -p $*-html
%.pdf: %.docbook.sgml
docbook-2-pdf --dssslproc openjade $<
.DELETE_ON_ERROR:
dh-kpatches-0.99.36+nmu2/doc/jadetex.cfg 0000644 0000000 0000000 00000000121 07623543375 014522 0 ustar \hypersetup{
bookmarks=true,
pdfstartview=FitH,
pdfproducer=sgml2x converter}
dh-kpatches-0.99.36+nmu2/doc/dh-kpatches.docbook.sgml 0000644 0000000 0000000 00000057650 07643377654 017145 0 ustar
]>
Packaging Linux kernel patches for Debian
Yann
Dirson
Debian
dirson@debian.org
$Revision: 1.14 $
This document describes a debhelper add-on mechanism that
allows consistent packaging of various kinds of Linux kernel
patches.
1.1
2000-06-10
Initial plain-text revision
1.4
2001-05-14
New "Depends" field
1.8
2002-02-08
New syntax "Kernel-version: all"
2002-02-10
Moved to DocBook, made it more of a real
manual
1.9
2002-02-14
Kernel-version ranges
1.10
2002-02-18
First description of "revision 1" format
1.12
2002-07-16
Integrated feedback from maintainers of
kpatch-packages. Default fields. Renamed operations.
Miscellaneous updates and additions.
1.13
2003-04-04
New field "Debian-patch-file"
Features
Current features
robustness of patch application
support for variable parameters on
patch>1>>
command line (eg. -p>)
allows to apply a version of a patch that was originally
targetted at another version
handles (un-)application of patch dependencies
records in kernel packages build with this patch applied
the name and version of the package which shipped the
patch.
Features to come with version 1.0
application of multi-part patches
support for file copying and archive unpacking as patch
operation, in addition to diff application
support for patch variants for different flavours of a
kernel, both to support heavy patches, and to help dealing
with otherwise overlaping patches
The dh_installkpatches> debhelper add-on
&DhtoolRefentry;
Description of the kpatches> file format
The syntax of kpatches> files is inspired by the
syntax of Debian control-files. A kpatches> file
contains sections, which are separated by one or more empty lines.
Each section is made of Key: value> lines.
Revision 0 kpatches files
This is the currently supported format for kpatches files.
It is to be superceded shortly with a new revision, more
general, described later in this document.
The file starts with a section for generic patch
information, and then has one for each patchfile, allowing
versions of the patch for many kernel versions to be specified
in one file.
The generic part
Mandatory fields
Patch-name
a short descriptive name for the patch
Patch-name's cannot contain "pipe" (|) and
"double quote" (") characters, for purely
implementation reasons. Patch-name's that contain
"slash" (/) characters would not be allowed before
dh-kpatches 0.99.3.
Examples
Patch-name: Kernel debugger
Patch-name: Tracing toolkit
Patch-name: Kernel crash dump
Patch-id
a short identifier for the patch
Examples
Patch-id: kdb
Patch-id: ltt
Patch-id: lkcd
Optional fields
Path-strip-level
default value for the per-patchfile field of the
same name (see below).
Architecture
default value for the per-patchfile field of the
same name (see below).
Depends
default value for the per-patchfile field of the
same name (see below).
The patchfile-specific parts
Mandatory fields
Patch-file
The name of the patch file. It may optionally be
compressed with gzip. This should be the first field of
each patchfile-specific section.
Kernel-version
The version (or range of versions) of the kernel
this patch is designed for. Other optional fields may
be introduced in the future to document other versions
which are known to work, and versions known not to
work.
Version ranges are specified as ver1> - ver2>>,
where both versions must belong to the same "kernel
branch" (eg. 2.2, or 2.4), and must be mentionned in
increasing order.
Kernel versions used in ranges should show
an empty EXTRAVERSION field. This is because no
special comparision scheme has been implemented to
handle the special meaning associated with
EXTRAVERSION values like pre2> or
test5>.
As a special case, the value "all" is allowed, for
patches that don't depend on a specific version (eg. if
they just add a set of files).
Optional fields
The optional fields, when not provided, all take
hopefully reasonable default values
Architecture
a comma-separated list of the debian identifiers
for archs supported by this patch.
Default is "all".
Path-strip-level
the value to pass as argument to the
patch>1>>
-p> option (aka --strip>).
Default is 1.
Depends
a comma-separated list of Patch-Id's of patches
this one depends on.
Default is no dependency.
Debian-patch-file
A special version of Patch-file, specifying that
a version of the patch file that only applies to a
Debian-patched kernel from a
kernel-source-version>>
package, in case the vanilla patch does not
fit.
Examples of revision 0 kpatches> files
kdb
These are the 2 kpatches> files for the
kernel-debugger patch. This patch was monolithic for 2.2
kernels, and has been split for recent 2.4 kernels into an
architecture-independant part and one architecture-dependant
part per supported architecture.
The architecture-independant kdb patch
The architecture-dependant kdb patches
Revision 1 kpatches files
This will be the next supported format for kpatches files.
It has not been implemented yet. It is described here for
public review.
There are 3 levels of information in this file. A
kernel-patch (1st level) is a set of patch alternatives (2nd
level), each of which is made of a sequence of patch operations
(3rd level).
The file starts with a section for generic patch
information, and then, for each alternative, has an
alternative-specific section followed by one section for each
patch operation.
An alternative section is syntactically distinguished from
an operation section by their mandatory constituent fields.
The generic part
Mandatory fields.
Kpatch-format-version
the version of the kpatches spec this files
complies with. For this version, it should be 1.
Patch-name
a short descriptive name for the patch
Patch-name's cannot contain "pipe" (|) and
"double quote" (") characters, for purely
implementation reasons. Patch-name's that contain
"slash" (/) characters would not be allowed before
dh-kpatches 0.99.3.
Examples
Patch-name: Kernel debugger
Patch-name: Tracing toolkit
Patch-name: Kernel crash dump
OS-kernel
The identifier of the kernel the patch is meant
for. Current possible values include linux>,
hurd>, netbsd>, and there is a
default value of linux>.
Patch-id
a short identifier for the patch
Examples
Patch-id: kdb
Patch-id: ltt
Patch-id: lkcd
Optional fields
For various fields in the alternative-specific and
operation-specific parts it can be useful to provide default
values. These are defined using fields named by prepending
Default-> to those fields names.
Examples include Default-Path-strip-level>
and Default-Architecture>.
The alternative-specific parts
A number of alternative-specific fields are used as
conditions> for this alternative to be considered.
This allows not only to specify in the same file versions of
the patch for many kernel versions, but also to specify
versions of the patch for different kernel
flavours>. For example, the LTT patch comes for 2 kernel
flavours: plain kernel, and RTAI-patched kernel.
The order of alternative sections is significant: the
1st alternative for which all conditions are fullfilled is
selected, and all further alternatives are ignored.
Mandatory fields
Kernel-version
This field is a condition.
The version (or range of versions) of the kernel
this patch is designed for. Other optional fields may
be introduced in the future to document other versions
which are known to work, and versions known not to
work.
Version ranges are specified as ver1> - ver2>>,
where both versions must belong to the same "kernel
branch" (eg. 2.2, or 2.4), and must be mentionned in
increasing order.
As a special case, the value "all" is allowed, for
patches that don't depend on a specific version (eg. if
they just add a set of files).
Optional fields
The optional fields, when not provided, all take
hopefully reasonable default values
Kernel-flavour
This field is a condition for this alternative
to be considered - a test to check whether a patch is
applied. It is not to be confused with
Depends>, which will pull others patches
first if they are not applied yet.
a comma-separated list of Patch-Id's of patches
that need to be applied for this one to be considered
for application. It may be necessary to
add support for flavour versionning (if a patch is
disruptive enough to warrant being qualified as a
flavour, it is likely that some of its evolution will
be disruptive as well). It
may be useful to add flavour negations, this has to be
investigated at some point.
Default is "" (plain/vanilla kernel).
Architecture
This field is a condition.
a comma-separated list of the debian identifiers
for archs supported by this patch.
Default is "all".
Depends
This field is NOT a condition.
a comma-separated list of Patch-Id's of patches
this one depends on. Patches in this list, as opposed
to those in the Kernel-flavour list, are such that
this patch cannot be applied without them.
Default is "" (no dependency).
The operation-specific parts
Mandatory fields
I have not firmly decided yet how to formalise these
parts, and I'm looking for opinions here.
I had originally elected to put the emphasis on
operations>; this is fine with "copy" and
"unpack", but "diff" usually refer to the inverse
operation (building the data), and "patch", despite being
used for this purpose for quite some time now, is already
being used here with a broader meaning. Another problem
with "unpack" is that it is broad enough so that the data
(ie. archive) may potentially be provided in several
formats (eg. tar.gz, tar.bz2, zip, etc.) - that will
require some (unnecessary) intelligence within the tool,
and will impair modularity (ie. adding support for more
archive formats using plugin modules).
Another alternative would be to put the emphasis on
the data>. That would mean replacing
Operation> fields with something like
Format> fields, which would have values like
"tree", "file", "diff", "tar.gz", "tar", etc. A careful
object-oriented implementation would take care of the
similarities between those.
Another one was suggested by Baruch Even - see below
for an example and some discussion.
Operation
The identifier for a type of patch operation.
Valid operations may include "diff", "copy", "unpack",
possibly depending on installed plugins. Other fields
in the section will depend on the value of this
field.
Types of operation
diff
The application of a diff file (aka. patch file)
to the kernel tree.
copy
The copy of a file, or of a directory tree into
the kernel tree.
unpack
The unpacking of a tarball (or other archive ?)
into the kernel tree.
Per-operation-type fields
Fields for the diff> operation
Mandatory fields
File
The name of the diff file.
Optional fields
Path-strip-level
the value to pass as argument to the
patch>1>>
-p> option (aka --strip>).
Default is 1.
Fields for the unpack> operation
Mandatory fields
File
The name of the archive file.
Optional fields
Path-strip-level
Similar to the option of the same name for
the diff> operation: strips the
N> first path components of each
member the archive.
Default is 0.
For tarballs, this option will probably
require pax>
1> to be
applicable.
Fields for the copy> operation
Mandatory fields
From
The path of the file or directory to copy.
To
The directory in which to copy it.
Examples of revision 1 kpatches> files
ltt
The Linux trace toolkit> provides
kernel patches both for vanilla kernels and for RTAI
kernels. Although there's not yet a packaged version of the
RTAI patch, here is what it would look like.
The LTT patch
lkcd
The kernel crash dump> patch requires
that a script be copied into the debian> part of
the kernel tree. Currently this is done by a creating a new
patch (named kerntypes>) with hand-written
apply> script, not taking advantage of the
dh-kpatches mechanism. Here is how it would look like in
revision 1:
The LKCD patch
Baruch Even baruch@debian.org> suggested a
syntax that may be simpler. Here is the same example
rewritten to use such a syntax, with some interpolations
from myself.
The LKCD patch (alternate version)
The description is more concise, but I fear it would
be too losely structured (much more of the information gets
stored in left-hand parts of statement), possibly leading to
strange-looking stanzas, and possibly impairing
extensibility. Here is what the expanded version of the
last sample (without default fields) would look like:
The LKCD patch (second alternate version)
In the same spirit, but datatype-driven instead of
operation-driven. This one lies somewhere in between
Baruch's proposal and my original one.
The LKCD patch (third alternate version)
dh-kpatches-0.99.36+nmu2/doc/lskpatches.refentry.sgml 0000644 0000000 0000000 00000004027 07623543375 017310 0 ustar
lskpatches
1
lskpatches
list installed kernel patches
lskpatches
Description
Prints on standard output a list of kernel patches installed
for kernel-package>. These patches are eligible
for the --added-patches> option of
make-kpkg> 1> .
Along with the IDs for those patches, it lists various
information, such as the architecture and kernel version on which
make-kpkg> will attempt to apply them, and, for patches
packaged using dh-kpatches>, it lists the version
of dh-kpatches> used to build the package, and the
kernel versions for which the package declares to provide a
patch.
See also
make-kpkg>1> ,
dh_installkpatches>1> .
Author
This tool and manual page were written by Yann Dirson
dirson@debian.org>.
Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free
Documentation License, Version 1.1 published by the Free Software
Foundation; with no Invariant Sections, no Front-Cover Texts and
no Back-Cover Texts. A copy of the license can be found under
/usr/share/common-licenses/FDL .
dh-kpatches-0.99.36+nmu2/.dh-kpatches.prcs_aux 0000644 0000000 0000000 00000004411 10251672506 015663 0 ustar ;; This file is automatically generated, editing may cause PRCS to do
;; REALLY bad things.
(Created-By-Prcs-Version 1 3 3)
(dh-kpatches.nw 32942 1118270411 4_dh_install 1.17.1.4.1.24.1.9)
(debian/README-kernelpatch 1389 1069373161 18_README-ker 1.3)
(debian/dh-kpatches.doc-base.dh-kpatches 399 1046215474 21_dh-kpatche 1.2)
(debian/rules 1448 1069007602 8_rules 1.8)
(examples-v1/kernel-patch-lkcd-alt.kpatches 304 1045350233 30_kernel-pat 1.1)
(doc/kpatch-policy.debiandoc.sgml 10386 1045349200 2_kpatch-pol 1.2)
(debian/dh-kpatches.files 230 1045350291 26_dh-kpatche 1.2)
(dh-kpatches.book 522 1068939313 41_dh-kpatche 1.1)
(examples-v1/kernel-patch-ltt.kpatches 433 1045350233 32_kernel-pat 1.1)
(debian/copyright 1010 1045338681 12_copyright 1.2)
(doc/jadetex.cfg 81 1045350141 25_jadetex.cf 1.1)
(debian/compat 2 1045350141 28_compat 1.1)
(examples-v1/kernel-patch-lkcd.kpatches 378 1045350233 31_kernel-pat 1.1)
(Makefile 1485 1070139836 3_Makefile 1.17)
(TODO 2755 1070146340 14_TODO 1.18)
(doc/dh_installkpatches.refentry-contents.sgml 3264 1045350573 1_dh_install 1.9)
(lskpatches 1755 1046216789 23_lskpatches 1.3)
(debian/kernel-patch-scripts.files 147 1045350475 27_kernel-pat 1.3)
(debian/changelog 20381 1118270743 13_changelog 1.25.1.23.1.11.1.8)
(debian/dh-kpatches.overrides 162 1045348736 15_overrides 1.1)
(debian/kernel-patch-scripts.overrides 93 1045350475 35_kernel-pat 1.1)
(doc/dh_installkpatches.refentry.sgml 275 1045349845 19_dh_install 1.1)
(debian/README 418 1069536855 42_README 1.1)
(apply.tmpl 6267 1063837106 7_apply.tmpl 1.30)
(examples/kernel-patch-kdb.kpatches.arch 331 1045349200 0_kdb-1.6.kp 1.2)
(register-patch 313 1045356505 33_register-p 1.4)
(dh_installkpatches.in 12383 1057179526 4_dh_install 1.17.1.4)
(doc/dh-kpatches.docbook.sgml 24488 1049493420 5_kpatches-s 1.14)
(examples/kernel-patch-kdb.kpatches.common 175 1045349200 17_kernel-pat 1.1)
(doc/Makefile 1355 1056491344 20_Makefile 1.8)
(examples-v1/kernel-patch-lkcd-alt3.kpatches 330 1045350475 34_kernel-pat 1.1)
(noweb.css 1240 1071004911 40_noweb.css 1.5)
(unpatch.tmpl 2484 1069374331 6_unpatch.tm 1.16)
(doc/lskpatches.refentry.sgml 2071 1045350141 24_lskpatches 1.1)
(debian/control 1299 1069007582 9_control 1.14)
(examples-v1/kernel-patch-lkcd-alt-expanded.kpatches 326 1045350233 29_kernel-pat 1.1)
dh-kpatches-0.99.36+nmu2/dh-kpatches.html 0000644 0000000 0000000 00000226406 10251655232 014734 0 ustar
dh-kpatches implementation
dh-kpatches implementation
The dh-kpatches system is made of two parts. The first one takes
patch descriptions, and produces kernel-patch packages; the second
one is (currently) contained in those patch packages, and handles
application of the patches to a kernel source tree, as well as
their removal.
The application/removal scripts are (currently) generated from
templates by the dh_installkpatches script for each
kernel-patch package.
Currently, the patch descriptions are completely parsed by
dh_installkpatches , and the apply/unpatch scripts are
specific to each package, and can only act on the patches
dh_installkpatches taught them about.
This is the debhelper-based script that will cause our packages
to install patches in the One True Way. Its base structure is
that of a standard debhelper script.
<dh_installkpatches.in>=
#!/usr/bin/perl -w
#
# dh_installkpatches $Revision: 1.17.1.4.1.24.1.5 $
#
# Reads debian/$package.kpatches[.foo], installs all files necessary
# to have make-kpkg use the kernel patches described in there.
#
# (c) 2000-2003 Yann Dirson <dirson@debian.org>
# Some parts based on code from Adam Di Carlo and Joey Hess
use strict;
use Debian::Debhelper::Dh_Lib;
init();
<definitions for the core kpatch system>
PACKAGE: foreach my $package (@{$dh{DOPACKAGES}}) {
my $tmp = tmpdir($package);
my $ext = pkgext($package);
# There are two filename formats, the usual
# plus an extended format (debian/package.*).
opendir (DEB,"debian/" ) || error("can't read debian directory: $!" );
# If this is the main package, we need to handle unprefixed filenames.
# For all packages, we must support both the usual filename format plus
# that format with a period an something appended.
my $regexp="\Q$package\E\." ;
if ($package eq $dh{MAINPACKAGE}) {
$regexp="(|$regexp)" ;
}
my @files = grep { /^${regexp}kpatches(\..*)?$/ } readdir (DEB);
closedir (DEB);
# next package if there are no patches in there
next PACKAGE if $#files < 0;
<process binary package $package>
}
For each binary package, all kpatches files are processed
to generate one apply script with a single diff
operation (and its corresponding unpatch script).
<process binary package $package>= (<-U )
<assert kpatch:depends is referenced in control file>
foreach my $file (@files) {
my %patchinfo = read_control_file ("debian/$file" );
# use Data::Dumper;
# print Dumper (%patchinfo);
my $patchid = $patchinfo{general}->{'patch-id' };
# transformation of the ID to be acceptable as part of an envvar's name
$patchinfo{general}->{'clean-patch-id' } = $patchinfo{general}->{'patch-id' };
$patchinfo{general}->{'clean-patch-id' } =~ s /-/_/g;
# protect pipes and dquotes for sed command-line
$patchinfo{general}->{'patch-name' } =~ s ,([|\"]),\\$1,g;
<generate apply/unpatch scripts for given $package and kpatches $file>
}
<set kpatch:Depends substvar>
A number of packages are needed by kernel-patch packages:
bash 2.x or better
because apply scripts use arrays
patch
because we (currently) only apply patches made of diff files
grep-dctrl
is used to register the version of the kernel-patch
package into the kernel-image package
<definitions for the core kpatch system>= (<-U ) [D-> ]
my $pkgdeps = "bash (>= 2.0), patch, grep-dctrl" ;
The substvar code was derived from similar functionnality in dh_perl
v3.4.1. For idempotency, we first remove anything this program might
have previously added to the substvars file.
<set kpatch:Depends substvar>= (<-U )
if (-e "debian/${ext}substvars" ) {
complex_doit("grep -v ^kpatch:Depends= debian/${ext}substvars > debian/${ext}substvars.new || true" );
doit("mv" , "debian/${ext}substvars.new" ,"debian/${ext}substvars" );
}
complex_doit("echo 'kpatch:Depends=$pkgdeps' >> debian/${ext}substvars" );
We also make sure the package uses our substvar, and abort if not.
<assert kpatch:depends is referenced in control file>= (<-U )
die 'debian/control must make package ' . $package . ' depend on ${kpatch:Depends}'
if system ("dpkg-gencontrol -p$package -Pdebian -O -T/dev/null -Vkpatch:Depends=KPATCHISUSED |"
. "grep -q '^Depends: .*KPATCHISUSED'" ) != 0;
For each v0 kpatches file, we produce an apply and an unpatch
script, necessary to work properly with make-kpkg. Those are
currently produced from templates.
<apply.tmpl>=
#! /bin/bash
set -e
<Assert this is a kernel tree>
<Apply.tmpl constants>
DEPENDS=(#DEPENDS#)
KVERSIONS=(#KVERSIONS#)
PATCHFILES=(#PATCHFILES#)
DEBPATCHFILES=(#DEBPATCHFILES#)
STRIPLEVELS=(#STRIPLEVELS#)
<Make apply idempotent>
<Get current kernel version>
<Select alternative to apply, as $IDX>
echo >&2 "START applying #PATCHID# patch (#PATCHNAME#)"
<Handle dependencies>
<Assert patch applies, using dry-run>
<Apply the patch>
<Store necessary info for unpatching>
<Create script to have this patch registered in doc-dir>
echo >&2 "END applying #PATCHID# patch"
<Get current kernel version>= (<-U )
VERSION=$(grep ^VERSION Makefile 2>/dev/null | \
sed -e 's/[^0-9]*\([0-9]*\)/\1/')
PATCHLEVEL=$( grep ^PATCHLEVEL Makefile 2>/dev/null | \
sed -e 's/[^0-9]*\([0-9]*\)/\1/')
SUBLEVEL=$(grep ^SUBLEVEL Makefile 2>/dev/null | \
sed -e 's/[^0-9]*\([0-9]*\)/\1/')
EXTRAVERSION=$(grep ^EXTRAVERSION Makefile | head -1 2>/dev/null | \
sed -e 's/EXTRAVERSION =[ ]*\([^ ]*\)$/\1/')
KERNELBRANCHLET=${VERSION}.${PATCHLEVEL}.${SUBLEVEL}
KERNELRELEASE=${KERNELBRANCHLET}${EXTRAVERSION}
The candidates patch version for application to our kernel (eg. 2.6.11.11)
is the first of:
the version passed through the KPATCH_* mechanism
the version exactly matching the kernel (eg. 2.6.11.11)
the version of the "branchlet" used for short stable branches in the 2.6 branch (eg. 2.6.11)
the all version
<Select alternative to apply, as $IDX>= (<-U )
IDX=
declare -i i=${#PATCHFILES[*]}-1
while [ $i -ge 0 ]
do
v=${KVERSIONS[$i]}
if [ -n "$KPATCH_#CLEANPATCHID#" -a "$v" = "$KPATCH_#CLEANPATCHID#" \
-o "$v" = "$KERNELRELEASE"
-o "$v" = "$KERNELBRANCHLET"
-o "$v" = all ]
then
IDX=$i
fi
i=i-1
done
<Assert we have an alternative to apply>
<Record parameters for applying alternative $IDX>
If the KPATCH_* mechanism was used, we have a special error message
listing the requested version.
<Assert we have an alternative to apply>= (<-U )
if [ -n "$KPATCH_#CLEANPATCHID#" -a ${KVERSIONS[$IDX]} != "$KPATCH_#CLEANPATCHID#" ]
then
echo >&2 "Requested kernel version \`$KPATCH_#CLEANPATCHID#' not found for patch #PATCHID#"
exit 1
elif [ -z "$IDX" ]
then
echo >&2 "No \"#PATCHNAME#\" patch found for kernel version $KERNELRELEASE"
exit 1
fi
Of special notice is the "debian" pseudo-flavour. Before the
kernel-patch-debian era, we had to check for README.Debian. Now we
must check for version.Debian.
<Record parameters for applying alternative $IDX>= (<-U )
KVERSION=${KVERSIONS[$IDX]}
STRIPLEVEL=${STRIPLEVELS[$IDX]}
if [ "${DEBPATCHFILES[$IDX]}" != '' -a \
\( -r version.Debian -o -r README.Debian \) ]
then
PATCHFILE=${DEBPATCHFILES[$IDX]}
else
PATCHFILE=${PATCHFILES[$IDX]}
fi
<Handle dependencies>= (<-U )
<Check for dependencies>
<Apply dependencies>
<Check for dependencies>= (<-U )
NEEDED_DEPS=
for dep in ${DEPENDS[$IDX]}
do
if [ -x ${TOPPATCHDIR}/${ARCHITECTURE}/${KERNELBRANCHLET}/apply/$dep ]
then
NEEDED_DEPS="${ARCHITECTURE}/${KERNELBRANCHLET}/apply/$dep $NEEDED_DEPS"
elif [ -x ${TOPPATCHDIR}/all/${KERNELBRANCHLET}/apply/$dep ]
then
NEEDED_DEPS="all/${KERNELBRANCHLET}/apply/$dep $NEEDED_DEPS"
elif [ -x ${TOPPATCHDIR}/${ARCHITECTURE}/apply/$dep ]
then
NEEDED_DEPS="${ARCHITECTURE}/apply/$dep $NEEDED_DEPS"
elif [ -x ${TOPPATCHDIR}/all/apply/$dep ]
then
NEEDED_DEPS="all/apply/$dep $NEEDED_DEPS"
else
echo >&2 "ERROR: Patch dependency \`$dep' not found - aborting"
echo >&2 "END applying #PATCHID# patch"
exit 1
fi
done
<Apply dependencies>= (<-U )
if [ "$NEEDED_DEPS" ]
then
echo >&2 "Ensuring the following patches are applied first: $NEEDED_DEPS"
for apply in ${NEEDED_DEPS}
do
dep=$(basename $apply)
${TOPPATCHDIR}/$apply
# check something was applied
if [ ! -f debian/APPLIED_${ARCHITECTURE}_$dep -a \
! -f debian/APPLIED_all_$dep ]
then
echo >&2 "ERROR: patch dependency did not left a patch stamp (version mismatch ?) - aborting"
echo >&2 "END applying #PATCHID# patch"
exit 1
fi
done
UNPATCHDEPS=$(echo ${NEEDED_DEPS} | sed s,/apply/,/unpatch/,g)
fi
<Assert patch applies, using dry-run>= (<-U )
echo >&2 "Testing whether \"#PATCHNAME#\" patch for $KVERSION applies (dry run):"
if ! [ -r $PATCHFILE ]
then
echo >&2 "\"#PATCHNAME#\" patch for $KVERSION not found"
exit 1
elif ! $DECOMPRESSOR $PATCHFILE |
patch --force --dry-run $PATCH_OPTIONS -p$STRIPLEVEL
then
echo >&2 "\"#PATCHNAME#\" patch for $KVERSION does not apply cleanly"
exit 1
fi
We do not use --force on second run, there should be no need for
it. If something requires interaction, it is likely there is a bug
somewhere, better catch it.
After applying the diff, we remove any empty files, so that files
"removed" by the diff are really removed. We make an exception for
./debian/ contents, and for files named APPLIED*, or else some (buggy)
stamp files may be caught too.
<Apply the patch>= (<-U )
if ! $DECOMPRESSOR $PATCHFILE |
patch $PATCH_OPTIONS -p$STRIPLEVEL
then
# This should never happen, thanks to the dry-run
echo >&2 "ASSERTION FAILED - \"#PATCHNAME#\" patch for $KVERSION failed"
echo >&2 "END applying #PATCHID# patch"
exit 1
fi
echo >&2 "\"#PATCHNAME#\" patch for $KVERSION succeeded"
<Remove empty files>
All information necessary for unpatching is stored in a
debian/APPLIED_* file, for use by the unpatch
script.
<Store necessary info for unpatching>= (<-U )
mkdir -p debian
cat > 'debian/APPLIED_#PATCHARCH#_#PATCHID#' <<EOF
PATCHFILE='$PATCHFILE'
STRIPLEVEL='$STRIPLEVEL'
DEPENDS='$UNPATCHDEPS'
EOF
<Create script to have this patch registered in doc-dir>= (<-U )
mkdir -p debian/image.d
PKGNAME=`dpkg -S $PATCHFILE | cut -d: -f1`
PKGVERS=`grep-dctrl -n -P $PKGNAME -s Version -X /var/lib/dpkg/status`
cat > 'debian/image.d/register-#PATCHID#' <<EOF
#!/bin/sh
# This scripts documents the "#PATCHNAME#" kernel patch into the
# kernel-image package, as being applied to the kernel.
docdir=\${IMAGE_TOP}/usr/share/doc/kernel-image-\${version}
mkdir -p \${docdir}
(
printf '#PATCHNAME# (#PATCHID#)${KPATCH_#CLEANPATCHID#:+ for kernel ${KPATCH_#CLEANPATCHID#}},'
echo ' from package $PKGNAME, version $PKGVERS'
) >> \${docdir}/applied-patches
EOF
chmod +x 'debian/image.d/register-#PATCHID#'
Generated by GNU enscript 1.6.4 .
<Apply.tmpl constants>= (<-U )
TOPPATCHDIR=/usr/src/kernel-patches
ARCHITECTURE=`dpkg --print-installation-architecture`
DECOMPRESSOR="zcat -f"
PATCH_OPTIONS="--ignore-whitespace --silent"
# This is informational only, used by lskpatches
DHPKPATCHES_VERSION=#DHKPVERS#
Generated by GNU enscript 1.6.4 .