summaryrefslogtreecommitdiffstats
path: root/dselect/methods/media
diff options
context:
space:
mode:
Diffstat (limited to 'dselect/methods/media')
-rw-r--r--dselect/methods/media/README.media106
-rw-r--r--dselect/methods/media/desc.media3
-rwxr-xr-xdselect/methods/media/install.sh282
-rw-r--r--dselect/methods/media/names1
-rwxr-xr-xdselect/methods/media/setup.sh489
-rwxr-xr-xdselect/methods/media/update.sh121
6 files changed, 1002 insertions, 0 deletions
diff --git a/dselect/methods/media/README.media b/dselect/methods/media/README.media
new file mode 100644
index 0000000..42be941
--- /dev/null
+++ b/dselect/methods/media/README.media
@@ -0,0 +1,106 @@
+Installation method for multiple binary media
+---------------------------------------------
+
+ This directory contains a method to be used within dselect in order to
+ access Debian binary packages stored across multiple binary media
+ (CDs, DVDs, BDs, or USBs).
+
+Acquiring package data
+---------------------
+
+ It is possible to access the following binary directories within
+ «dists/stable»:
+
+ . main
+ . contrib
+ . non-free-firmware
+ . non-free
+ . local
+
+ The selected method will try to read the «Packages.cd» file from each
+ of these directories if it is available.
+
+Identifying the media
+----------------------
+
+ A unique name is associated to each media disc. This name should correspond
+ with the label on the front of the media disc. The name is also available on
+ the media disc, so the system can find out which media disc is inserted into
+ the computer at any time.
+
+Installing the files
+--------------------
+
+ At the beginning of the installation the “media” method will sort the list
+ of to-be-installed packages and install them media disc by media disc. If a
+ different media disc is required the user will be prompted to exchange
+ the media disc.
+
+Preparing multiple binary media discs
+-------------------------------------
+
+ Since the “media” method needs to know which packages are on which
+ media disc one cannot use regular «Packages» files. An additional data
+ field «X-Medium:» is required. The first media disc from the set should
+ contain all «Packages.cd» files. To be more convenient you should
+ include the «Packages.cd» files on all media discs. This ensures that
+ you do not have to start with the first media disc all the time.
+
+ Additionally the package needs to gain information which media disc is
+ currently used. Thus each media disc contains the file «.disk/info»
+ which contains the symbolic name for the media disc as specified by
+ «X-Medium:».
+
+ In order to be able to create the modified «Packages.cd» files, you
+ have to use the «-M medium» option of dpkg-scanpackages (supported
+ in dpkg-dev since 1.15.5).
+
+ To split the “main” distribution into two media discs you will need to
+ create a «Packages.cd» file for each «binary-$arch» directory.
+ Afterwards you simply append the second one to the first one and
+ put the resulting «Packages.cd» file into both «binary-$arch»
+ directories.
+
+Sample Layout
+-------------
+
+ Media disc 1 .disk/info = "Debian GNU/Linux binary-amd64"
+ dists/stable/main/binary-all/
+ binary-amd64/Packages.cd.gz
+ binary-amd64/net/foo.deb
+ contrib/binary-amd64/Packages.cd.gz
+ non-free-firmware/binary-amd64/Packages.cd.gz
+ non-free/binary-amd64/Packages.cd.gz
+
+ Media disc 2 .disk/info = "Debian GNU/Linux contrib-amd64"
+ dists/stable/main/binary-amd64/Packages.cd.gz
+ contrib/binary-all/
+ binary-amd64/Packages.cd.gz
+ binary-amd64/net/foo.deb
+ non-free-firmware/binary-amd64/Packages.cd.gz
+ non-free/binary-amd64/Packages.cd.gz
+
+ Media disc 3 .disk/info = "Debian GNU/Linux non-free-amd64"
+ dists/stable/main/binary-amd64/Packages.cd.gz
+ contrib/binary-amd64/Packages.cd.gz
+ non-free-firmware/binary-amd64/Packages.cd.gz
+ non-free/binary-all/
+ binary-amd64/Packages.cd.gz
+ binary-amd64/net/foo.deb
+
+ To re-generate the Packages file you have to change directory into
+ «dists/stable/$part» and issue «dpkg-scanpackages» as follows. It is
+ assumed that you use regular compressed overrides files in
+ «/pub/debian/indices».
+
+ Media disc 1: dpkg-scanpackages -M "Debian GNU/Linux binary-amd64" \
+ binary-amd64 /pub/debian/indices/override.buster.gz \
+ dists/stable/ > binary-amd64/Packages
+
+ Media disc 2: dpkg-scanpackages -M "Debian GNU/Linux contrib-amd64" \
+ binary-amd64 /pub/debian/indices/override.buster.contrib.gz \
+ dists/stable/ > binary-amd64/Packages
+
+ Media disc 3: dpkg-scanpackages -M "Debian GNU/Linux non-free-amd64" \
+ binary-amd64 /pub/debian/indices/override.buster.non-free.gz \
+ dists/stable/ > binary-amd64/Packages
diff --git a/dselect/methods/media/desc.media b/dselect/methods/media/desc.media
new file mode 100644
index 0000000..e76022e
--- /dev/null
+++ b/dselect/methods/media/desc.media
@@ -0,0 +1,3 @@
+Installation from a media set containing a Debian distribution. The
+media discs may be or not be mounted already and should contain a standard
+ISO9660 media filesystem.
diff --git a/dselect/methods/media/install.sh b/dselect/methods/media/install.sh
new file mode 100755
index 0000000..91e717d
--- /dev/null
+++ b/dselect/methods/media/install.sh
@@ -0,0 +1,282 @@
+#!/bin/sh
+#
+# Copyright © 1995-1998 Ian Jackson <ijackson@chiark.greenend.org.uk>
+# Copyright © 1998 Heiko Schlittermann <hs@schlittermann.de>
+#
+# This 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, see <https://www.gnu.org/licenses/>.
+
+set -e
+vardir="$1"
+method=$2
+option=$3
+
+cd "$vardir/methods/$method"
+
+. ./shvar.$option
+
+#debug() { echo "DEBUG: $@"; }
+debug() {
+ true
+}
+iarch=$(dpkg --print-architecture)
+
+# 1/ mountpoint
+# 2/ hierarchy
+getdisklabel () {
+ debug "$1" "$2"
+ if [ -f $1/.disk/info ]; then
+ echo -n $(head -1 "$1/.disk/info")
+ elif [ -f $1$2/.disk/info ]; then
+ echo -n $(head -1 "$1$2/.disk/info")
+ else
+ echo -n 'Non-Debian disc'
+ fi
+}
+
+xit=1
+
+do_umount() {
+ if [ -n "$umount" ]; then
+ echo umount "$umount"
+ #">/dev/null" "2>&1"
+ fi
+}
+
+do_mount() {
+ if [ ! -b "$p_blockdev" ]; then
+ loop=",loop"
+ fi
+
+ if [ -n "$p_blockdev" ]; then
+ umount="$p_mountpoint"
+ echo mount -rt iso9660 -o nosuid,nodev${loop} "$p_blockdev" "$p_mountpoint"\; umount="$p_mountpoint"
+ fi
+}
+
+trap 'eval $(do_umount); exit $xit' 0
+
+eval $(do_mount)
+
+predep="$vardir/predep-package"
+while true; do
+ thisdisk="$(getdisklabel ${p_mountpoint} ${p_hierbase})"
+ set +e
+ dpkg --predep-package >"$predep"
+ rc=$?
+ set -e
+ if test $rc = 1; then
+ break
+ fi
+ test $rc = 0
+
+ perl -e '
+ ($binaryprefix,$predep,$thisdisk) = @ARGV;
+ open(P, "< $predep") or die "cannot open $predep: $!\n";
+ while (<P>) {
+ s/\s*\n$//;
+ $package = $_ if s/^Package: //i;
+ /^X-Medium:\s+(.*)\s*/ and $medium = $1;
+ @filename = split(/ /,$_) if s/^Filename: //i;
+ @msdosfilename = split(/ /,$_) if s/^MSDOS-Filename: //i;
+ }
+ die "internal error - no package" if length($package) == 0;
+ die "internal error - no filename" if not @filename;
+ die "internal error - mismatch >@filename< >@msdosfilename<"
+ if @filename && @msdosfilename &&
+ @filename != @msdosfilename;
+ if ($medium && ($medium ne $thisdisk)) {
+ print "
+
+This is
+ $thisdisk
+However, $package is expected on disc:
+ $medium
+Please change the discs and press <RETURN>.
+
+";
+ exit(1);
+ }
+ @invoke = (); $| =1;
+ for ($i = 0; $i <= $#filename; $i++) {
+ $ppart = $i+1;
+ print "Looking for part $ppart of $package ... ";
+ if (-f "$binaryprefix$filename[$i]") {
+ $print = $filename[$i];
+ $invoke = "$binaryprefix$filename[$i]";
+ } elsif (-f "$binaryprefix$msdosfilename[$i]") {
+ $print = $msdosfilename[$i];
+ $invoke = "$binaryprefix$msdosfilename[$i]";
+ } else {
+ $base = $filename[$i]; $base =~ s,.*/,,;
+ $msdosbase = $msdosfilename[$i]; $msdosbase =~ s,.*/,,;
+ $c = open(X, "-|"));
+ if (not defined $c) {
+ die "failed to fork for find: $!\n";
+ }
+ if (!$c) {
+ exec("find", "-L",
+ length($binaryprefix) ? $binaryprefix : ".",
+ "-name",$base,"-o","-name",$msdosbase);
+ die "failed to exec find: $!\n";
+ }
+ while (chop($invoke = <X>)) { last if -f $invoke; }
+ $print = $invoke;
+ if (substr($print,0,length($binaryprefix)+1) eq
+ "$binaryprefix/") {
+ $print = substr($print,length($binaryprefix));
+ }
+ }
+ if (!length($invoke)) {
+ warn "
+
+Cannot find the appropriate file(s) anywhere needed to install or upgrade
+package $package. Expecting version $version or later, as listed in the
+Packages file.
+
+Perhaps the package was downloaded with an unexpected name? In any case,
+you must find the file(s) and then either place it with the correct
+filename(s) (as listed in the Packages file or in $vardir/available)
+and rerun the installation, or upgrade the package by using
+\"dpkg --install --auto-deconfigure" by hand.
+
+";
+ exit(1);
+ }
+ print "$print\n";
+ push(@invoke,$invoke);
+ }
+ print "Running dpkg -iB for $package ...\n";
+ exec("dpkg","-iB","--",@invoke);
+ die "failed to exec dpkg: $!\n";
+ ' -- "$p_mountpoint$p_hierbase" "$predep" "$thisdisk"
+done
+
+perl -e '
+ $SIG{INT} = sub { cd $vardir; unlink <tmp/*>; exit 1; };
+ $| = 1;
+ my ($vardir, $mountpoint, $hierbase, $mount, $umount) = @ARGV;
+ my $line;
+ my $AVAIL = "$vardir/methods/media/available";
+ my $STATUS = "$vardir/status";
+ my %Installed, %Filename, %Medium;
+ print "Get currently installed package versions...";
+ open(IN, "$STATUS") or die "cannot open $STATUS: $!\n";
+ $line = 0;
+ { local $/ = "";
+ while (<IN>) {
+ my %status;
+ my @pstat;
+ $line++ % 20 or print ".";
+ s/\n\s+/ /g;
+ %status = ("", split /^(\S*?):\s*/m, $_);
+ map { chomp $status{$_}; $status{$_} =~ s/^\s*(.*?)\s*$/$1/;} keys %status;
+ @pstat = split(/ /, $status{Status});
+ next unless ($pstat[0] eq "install");
+ if ($pstat[2] eq "config-files" || $pstat[2] eq "not-installed") {
+ $Installed{$status{Package}} = "0.0";
+ } else {
+ $Installed{$status{Package}} = $status{Version} || "" ;
+ }
+ }; }
+ print "\nGot ", scalar keys %Installed, " installed/pending packages\n";
+ print "Scanning available packages...";
+ $line = 0;
+ open(IN, "$AVAIL") or die("Cannot open $AVAIL: $!\n");
+ { local $/ = "";
+ while (<IN>) {
+ my $updated;
+ $line++ % 20 or print ".";
+
+ s/\n\s+/ /g;
+ %avail = ("", split /^(\S*?):\s*/m, $_);
+ map { chomp $avail{$_}; $avail{$_} =~ s/^\s*(.*?)\s*$/$1/;} keys %avail;
+
+ next unless defined $Installed{$avail{Package}};
+
+ system "dpkg", "--compare-versions", $avail{Version}, "gt", $Installed{$avail{Package}};
+ $updated = ($? == 0);
+ #print "$avail{Package}(" . ($updated ? "+" : "=") . ") ";
+ $updated or next;
+
+ $Filename{$avail{Package}} = $avail{Filename};
+
+ next unless defined $avail{"X-Medium"};
+ ${Medium{$avail{"X-Medium"}}} or ${Medium{$avail{"X-Medium"}}} = [];
+ push @{${Medium{$avail{"X-Medium"}}}}, $avail{Package};
+ }; };
+ print "\n";
+
+ if (@_ = keys(%Medium)) {
+ print "You will need the following distribution disc(s):\n",
+ join (", ", @_), "\n";
+ }
+
+ foreach $need (sort @_) {
+ if (-r "$mountpoint/.disk/info") {
+ open(IN, "$mountpoint/.disk/info") or die("$mountpoint/.disk/info: $!\n");
+ } else {
+ open(IN, "$mountpoint/$hierbase/.disk/info") or die("$mountpoint/$hierbase/.disk/info: $!\n");
+ }
+ $disk = <IN>; chomp $disk; close(IN);
+
+ print "Processing disc\n $need\n";
+
+ while ($disk ne $need) {
+ print "Wrong disc. This is disc\n $disk\n";
+ print "However, the needed disc is\n $need\n";
+ print "Please change the discs and press <RETURN>\n";
+ system($umount);
+ <STDIN>;
+ system($mount);
+ $? and warn("cannot mount $mount\n");
+ } continue {
+ if (-r "$mountpoint/.disk/info") {
+ open(IN, "$mountpoint/.disk/info") or die("$mountpoint/.disk/info: $!\n");
+ } else {
+ open(IN, "$mountpoint/$hierbase/.disk/info") or die("$mountpoint/$hierbase/.disk/info: $!\n");
+ }
+ $disk = <IN>; chomp $disk; close(IN);
+ }
+
+ -d "tmp" || mkdir "tmp", 0755 or die("Cannot mkdir tmp: $!\n");
+ unlink <tmp/*>;
+
+ print "creating symlinks...\n";
+ foreach (@{$Medium{$need}}) {
+ ($basename = $Filename{$_}) =~ s/.*\///;
+ symlink "$mountpoint/$hierbase/$Filename{$_}",
+ "tmp/$basename";
+ }
+ chdir "tmp" or die "cannot chdir to tmp: $!\n";
+ system "dpkg", "-iGROEB", ".";
+ unlink <*>;
+ chdir "..";
+
+ if ($?) {
+ print "\nThe dpkg run produced errors. Please state whether to\n",
+ "continue with the next media disc. [Y/n]: ";
+ $answer = <STDIN>;
+ exit 1 if $answer =~ /^n/i;
+ $ouch = $?;
+ }
+ }
+
+ exit $ouch;
+
+' "$vardir" "$p_mountpoint" "$p_hierbase" "$(do_mount)" "$(do_umount)"
+
+echo -n 'Installation OK. Hit RETURN. '
+read response
+
+xit=0
diff --git a/dselect/methods/media/names b/dselect/methods/media/names
new file mode 100644
index 0000000..1d8879d
--- /dev/null
+++ b/dselect/methods/media/names
@@ -0,0 +1 @@
+31 media Install from a media set (CDs, DVDs, BDs, USBs).
diff --git a/dselect/methods/media/setup.sh b/dselect/methods/media/setup.sh
new file mode 100755
index 0000000..5bf3642
--- /dev/null
+++ b/dselect/methods/media/setup.sh
@@ -0,0 +1,489 @@
+#!/bin/sh
+#
+# Copyright © 1995-1998 Ian Jackson <ijackson@chiark.greenend.org.uk>
+# Copyright © 1998 Heiko Schlittermann <hs@schlittermann.de>
+# Copyright © 1998-1999 Martin Schulze <joey@infodrom.north.de>
+#
+# This 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, see <https://www.gnu.org/licenses/>.
+
+set -e
+vardir="$1"
+method=$2
+option=$3
+
+test -d "$vardir/methods/$method" || mkdir "$vardir/methods/$method"
+cd "$vardir/methods/$method"
+tp="$(mktemp --tmpdir $method.XXXXXXXXXX)"
+
+iarch=$(dpkg --print-architecture)
+dist=stable
+
+xit=1
+trap '
+ rm -f $tp.?
+ if [ -n "$umount" ]; then
+ umount "$umount" >/dev/null 2>&1
+ fi
+ exit $xit
+' 0
+
+if ls -d "$tp.?" >/dev/null 2>&1; then
+ rm $tp.?
+fi
+
+#debug() { echo "DEBUG: $@"; }
+debug() {
+ true
+}
+ismulti() {
+ debug $1 $2; test -e "$1/.disk/info" || test -e "$1$2/.disk/info"
+}
+
+# 1/ mountpoint
+# 2/ hierarchy
+getdisklabel () {
+ debug "$1" "$2"
+ if [ -f $1/.disk/info ]; then
+ echo -n $(head -1 "$1/.disk/info")
+ elif [ -f $1$2/.disk/info ]; then
+ echo -n $(head -1 "$1$2/.disk/info")
+ else
+ echo -n 'Non-Debian disc'
+ fi
+}
+
+yesno () {
+ while true; do
+ echo -n "$2 [$1] "
+ read response
+ if [ -z "$response" ]; then
+ response="$1"
+ fi
+ case "$response" in
+ [Nn]*)
+ yesno=no
+ return
+ ;;
+ [Yy]*)
+ yesno=yes
+ return
+ ;;
+ esac
+ done
+}
+
+getblockdev () {
+ mountpoint="$vardir/methods/mnt"
+ if [ -z "$defaultdevice" ]; then
+ defaultdevice="$newdefaultdevice"
+ elif [ "$defaultdevice" != "$newdefaultdevice" ]; then
+ echo "Last time you specified installation from $defaultdevice."
+ fi
+ promptstring="$1"
+ while [ -z "$blockdevice" ]; do
+ echo -n "$promptstring [$defaultdevice]: "
+ read response
+ if [ -z "$response" ]; then
+ response="$defaultdevice"
+ fi
+ if [ ! -b "$response" ]; then
+ echo "$response is not a block device - will try as loopback."
+ loop=",loop"
+ fi
+ tryblockdevice="$response"
+ fstype=iso9660
+ umount="$mountpoint"
+ if mount -rt "$fstype" -o nosuid,nodev$loop "$tryblockdevice" "$mountpoint"
+ then
+ echo
+ blockdevice="$tryblockdevice"
+ else
+ umount=""
+ echo "Unable to mount $tryblockdevice on $mountpoint, type $fstype."
+ fi
+ done
+}
+
+outputparam () {
+ echo "$2" | sed -e "s/'/'\\\\''/; s/^/$1='/; s/$/'/" >&3
+}
+
+## MAIN
+intrkey="$(stty -a | sed -n 's/.*intr = \([^;]*\);.*/\1/p')"
+echo "
+If you make a mistake, use the interrupt key ($intrkey) to abort.
+"
+
+# State variables, “best first”
+# {main,ctb,nf,lcl}_{packages,binary}
+# Empty before we've found them or if they're not available,
+# set to the relevant bit under mountpoint otherwise.
+# hierbase
+# A directory containing a Debian FTP site mirror tree.
+# mountpoint
+# The mountpoint for the filesystem containing the stuff
+# empty or unset if we don't know yet, or if we haven't mounted anything;
+# may also be empty if ‘directory’ was set.
+# blockdevice
+# The actual block device to mount.
+# fstype
+# The filesystem type to use.
+# defaultdevice
+# The default block device to mount.
+
+p_usedevel=no
+if [ -f shvar.$option ]; then
+ . ./shvar.$option
+ defaultdevice="$p_blockdev"
+ usedevel="$p_usedevel"
+fi
+
+mount >$tp.m
+sed -n 's/ ([^)]*)$//; s/^[^ ]* on //; s/ type iso9660$//p' <$tp.m >$tp.l
+ncdroms=$(wc -l <$tp.l)
+if [ $ncdroms -gt 1 ]; then
+ response=""
+ while [ -z "$response" ]; do
+ echo 'Several media discs (ISO9660 filesystems) are mounted:'
+ grep -E 'type iso9660 \([^)]*\)$' <$tp.m | nl
+ echo -n "Is it any of these ? Type a number, or 'n' for none. "
+ read response
+ response="$(echo "$response" | sed -e 's/[ ]*$//')"
+ if expr "$response" : '[0-9][0-9]*$' >/dev/null && \
+ [ $response -ge 1 -a $response -le $ncdroms ]; then
+ mountpoint="$(sed -n $response'p' <$tp.l)"
+ echo
+ elif expr "$response" : '[Nn]' >/dev/null; then
+ mountpoint=""
+ else
+ response=""
+ fi
+ done
+elif [ $ncdroms = 1 ]; then
+ mountpoint="$(cat $tp.l)"
+ perl -ne 'print if s/ type iso9660 \([^)]*\)$// && s/ on .*$//;' \
+ <$tp.m >$tp.d
+ blockdevice="$(cat $tp.d)"
+ yesno yes \
+ "Found a media disc: $blockdevice, mounted on $mountpoint. Is it the right one?"
+ if [ $yesno = no ]; then
+ echo 'Unmounting it ...'
+ umount="$mountpoint"
+ while true; do
+ echo -n 'Please insert the right disc, and hit return: '
+ read response
+ if mount -rt iso9660 -o nosuid,nodev \
+ "$blockdevice" "$mountpoint"; then
+ echo
+ break
+ fi
+ done
+ fi
+fi
+if [ -z "$mountpoint" ]; then
+ if [ -b /dev/cdrom ]; then
+ echo 'Found that /dev/cdrom exists and is a block device.'
+ newdefaultdevice=/dev/cdrom
+ fi
+ getblockdev 'Insert the media and enter the block device name'
+fi
+
+if [ -n "$mountpoint" ]; then
+ # We must have $mountpoint
+ echo \
+'All directory names should be entered relative to the root of the media disc.
+'
+fi
+
+# now try to get the users idea where the debian
+# hierarchy start below the mointpoint
+
+debug "mountpoint: $mountpoint"
+while true; do
+ if ismulti "${mountpoint}" "${hierbase}"; then
+ multi=yes
+ fi
+
+ echo \
+"Need to know where on the media disc the top level of the Debian
+distribution is - this will usually contain the 'dists' directory.
+
+If the media disc is badly organized and doesn't have a straightforward copy of
+the distribution you may answer 'none' and the needed parts will be prompted
+individually."
+
+ defhierbase=none
+ if [ -n "$p_hierbase" ]; then
+ if [ -d "$mountpoint/$p_hierbase/dists/$dist/main/binary-$iarch" \
+ -o -n "$multi" ]; then
+ echo "Last time you said '$p_hierbase', and that looks plausible."
+ defhierbase="$p_hierbase"
+ else
+ echo "
+Last time you said '$p_hierbase', but that doesn't look plausible,
+since '$p_hierbase/dists/$dist/main/binary-$iarch' doesn't seem to exist.
+And it does not appear that you are using a multiple media set."
+ fi
+ fi
+
+ # at this point defhierbase is set if it looks plausible
+ # if ‘none’ was entered, we assume a media with a debian/ directory
+
+ if [ none = "$defhierbase" -a -d "$mountpoint/debian/dists/$dist/main/binary-$iarch" ]
+ then
+ echo "'/debian' exists and looks plausible, so that's the default."
+ defhierbase=/debian
+ fi
+
+ echo -n "Distribution top level ? [$defhierbase] "
+ read response
+ if [ -z "$response" ]; then
+ response="$defhierbase"
+ fi
+ if [ none = "$response" ]; then
+ hierbase=""
+ break
+ elif ismulti "$mountpoint" "$response" && [ -z "$multi" ]; then
+ multi=yes
+ fi
+
+ if ! [ -d "$mountpoint/$response/dists/$dist/main/binary-$iarch" \
+ -o -n "$multi" ]; then
+ echo \
+"Neither $response/dists/$dist/main/binary-$iarch does not exist,
+nor are you using a multiple media set"
+ break
+ fi
+
+ hierbase="$(echo "$response" | sed -e 's:/$::; s:^/*:/:; s:/\+:/:g;')"
+ debug "hierbase: [$hierbase]"
+
+ if [ -n "$multi" ]; then
+ disklabel=$(getdisklabel "$mountpoint" "/$response")
+ echo "Ok, this is disc"
+ echo " $disklabel"
+ #echo "Updating multiple media contents file cache ..."
+ #multi_contentsfile="${mountpoint}/${response}/.disk/contents.gz"
+ #zcat "$multi_contentsfile" > disk-contents.$option
+ fi
+
+ break;
+done
+
+distribution=$dist
+if [ -n "$hierbase" ]; then
+ if [ -d "$mountpoint/$hierbase/dists/unstable/binary-$iarch" ]; then
+ echo \
+'
+Both a stable released distribution and a work-in-progress
+development tree are available for installation. Would you like to
+use the unreleased development tree (this is only recommended for
+experts who like to live dangerously and want to help with testing) ?'
+ yesno "$p_usedevel" 'Use unreleased development distribution ?'
+ usedevel="$yesno"
+ if [ "$usedevel" = yes ]; then
+ distribution=development
+ fi
+ else
+ usedevel=no
+ fi
+ echo
+fi
+
+case "$hierbase" in
+/* )
+ ;;
+'' )
+ ;;
+* )
+ hierbase="/$hierbase"
+ ;;
+esac
+
+check_binary () {
+ # args: area-in-messages directory
+ debug "check_binary($@)"
+
+ if [ ! -d "${mountpoint}$2" -a -z "$multi" ]; then
+ echo "'$2' does not exist."
+ return
+ fi
+
+# In this special case it is ok for a sub-distribution to not contain any
+# .deb files. Each media should contain all Packages.cd files but does not
+# need to contain the .deb files.
+#
+# if ! { find -L "$mountpoint$2" -name '*.deb' -print \
+# | head -1 | grep . ; } >/dev/null 2>&1 && [ -z "$multi" ];
+# then
+# echo "'$2' does not contain any *.deb packages."
+# return
+# fi
+
+ this_binary="$2"
+ echo -n "Using '$this_binary' as $1 binary directory"
+
+ if [ -n "$multi" ]; then
+ this_disk=$(getdisklabel ${mountpoint} "/$hierbase")
+ echo " from disc"
+ echo " '$this_disk'"
+ else
+ echo ""
+ fi
+}
+
+find_area () {
+ # args: area-in-messages area-in-vars subdirectory-in-hier
+ # last-time-binary last-time-packages
+ debug "find_area($@)"
+ this_binary=''
+ this_packages=''
+ this_disk=''
+ if [ -n "$hierbase" ]; then
+ check_binary $1 $(echo "$hierbase/dists/$3/$1/binary-$iarch" | sed 's:/\+:/:g')
+ debug "THIS_BINARY $this_binary"
+ fi
+ if [ $2 = nf -a -z "$this_binary" ]; then
+ echo "
+Note: most media distributions of Debian do not include programs available
+in the 'non-free' directory of the distribution site.
+This is because these programs are under licenses that do not allow source
+modification or prevent distribution for profit on a media, or other
+restrictions that make them not free software.
+If you wish to install these programs you will have to get them from an
+alternative source."
+ fi
+ while [ -z "$this_binary" ]; do
+ defaultbinary="$4"
+ echo "
+Which directory contains the *.deb packages from the $1 distribution
+area (this directory is named '$3/binary' on the distribution site) ?
+Say 'none' if this area is not available."
+ if [ $2 != main -a -z "$defaultbinary" ]; then
+ defaultbinary=none
+ fi
+ echo -n \
+"Enter _$1_ binary directory. [$4]
+ ? "
+ read response
+ if [ -z "$response" -a -n "$defaultbinary" ]; then
+ response="$defaultbinary"
+ fi
+ if [ none = "$response" ]; then
+ break
+ fi
+ case "$response" in
+ '' | none)
+ continue
+ ;;
+ esac
+ check_binary $1 "$(echo "$response" | sed -e 's:/$::; s:^/*:/:')"
+ done
+ if [ -n "$this_binary" ]; then
+ if [ "$multi" = "yes" ]; then
+ for f in Packages.cd.gz packages.cd.gz Packages.cd packages.cd; do
+ if [ -f "$mountpoint/$this_binary/$f" ]; then
+ this_packages="$this_binary/$f"
+ echo "Using '$this_packages' for $1."
+ break
+ fi
+ done
+ elif [ -f "${mountpoint}${hierbase}/.disk/packages/$1/Packages.gz" ]; then
+ this_packages=$(echo "${hierbase}/.disk/packages/$1/Packages.gz"|sed 's:/\+:/:g')
+ echo "Using '${this_packages}' for $1."
+ fi
+ while [ -z "$this_packages" ]; do
+ echo -n "
+Cannot find the $1 'Packages.cd' file. The information in the
+'Packages.cd' file is important for package selection during new
+installations, and is very useful for upgrades.
+
+If you overlooked it when downloading you should do get it now and
+return to this installation procedure when you have done so: you will
+find one Packages.cd file and one Packages.cd.gz file -- either will do --
+in the 'binary' subdirectory of each area on the FTP sites and
+media discs. Alternatively (and this will be rather slow) the packages in
+the distribution area can be scanned - say 'scan' if you want to do so.
+
+You need a separate Packages.cd file from each of the distribution areas
+you wish to install.
+
+Where is the _$1_ 'Packages.cd' file (if none is available, say 'none')
+[$5]
+ ? "
+ read response
+ if [ -z "$response" -a -n "$5" ]; then
+ response="$5"
+ fi
+ case "$response" in
+ '')
+ break
+ ;;
+ none)
+ break
+ ;;
+ scan)
+ this_packages=scan
+ ;;
+ /*)
+ this_packages="$response"
+ ;;
+ *)
+ this_packages="/$response"
+ ;;
+ esac
+ done
+ fi
+ eval $2'_binary="$this_binary"'
+ eval $2'_packages="$this_packages"'
+ eval $2'_disk="$this_disk"'
+}
+
+find_area main main "$distribution" "$p_main_binary" "$p_main_packages"
+find_area contrib ctb "$distribution" "$p_ctb_binary" "$p_ctb_packages"
+find_area non-free-firmware nff "$distribution" "$p_nff_binary" "$p_nff_packages"
+find_area non-free nf "$distribution" "$p_nf_binary" "$p_nf_packages"
+find_area local lcl local "$p_lcl_binary" "$p_lcl_packages"
+
+echo -n '
+Hit RETURN to continue. '
+read response
+
+exec 3>shvar.$option.new
+
+outputparam p_blockdev "$blockdevice"
+outputparam p_fstype "$fstype"
+outputparam p_mountpoint "$mountpoint"
+outputparam p_hierbase "$hierbase"
+outputparam p_usedevel "$usedevel"
+outputparam p_main_packages "$main_packages"
+outputparam p_main_binary "$main_binary"
+outputparam p_main_disk "$main_disk"
+outputparam p_ctb_packages "$ctb_packages"
+outputparam p_ctb_binary "$ctb_binary"
+outputparam p_ctb_disk "$ctb_disk"
+outputparam p_nff_packages "$nff_packages"
+outputparam p_nff_binary "$nff_binary"
+outputparam p_nff_disk "$nff_disk"
+outputparam p_nf_packages "$nf_packages"
+outputparam p_nf_binary "$nf_binary"
+outputparam p_nf_disk "$nf_disk"
+outputparam p_lcl_packages "$lcl_packages"
+outputparam p_lcl_binary "$lcl_binary"
+outputparam p_multi "$multi"
+outputparam p_multi_contentsfile "$multi_contentsfile"
+
+mv shvar.$option.new shvar.$option
+
+xit=0
diff --git a/dselect/methods/media/update.sh b/dselect/methods/media/update.sh
new file mode 100755
index 0000000..f0a703f
--- /dev/null
+++ b/dselect/methods/media/update.sh
@@ -0,0 +1,121 @@
+#!/bin/sh
+#
+# Copyright © 1995-1998 Ian Jackson <ijackson@chiark.greenend.org.uk>
+# Copyright © 1998 Heiko Schlittermann <hs@schlittermann.de>
+#
+# This 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, see <https://www.gnu.org/licenses/>.
+
+set -e
+vardir="$1"
+method=$2
+option=$3
+iarch=$(dpkg --print-architecture)
+
+cd "$vardir/methods/$method"
+
+. ./shvar.$option
+
+#debug() { echo "DEBUG: $@"; }
+debug() {
+ true
+}
+
+packages=0
+for f in main ctb nf lcl; do
+ eval 'this_packages=$p_'$f'_packages'
+
+ if [ -n "$this_packages" ]; then
+ packages=1
+ fi
+done
+
+if [ $packages eq 0 ]; then
+ echo '
+No Packages files available, cannot update available packages list.
+Hit RETURN to continue. '
+ read response
+ exit 0
+fi
+
+xit=1
+trap '
+ for area in main ctb nf lcl; do
+ rm -f packages-$area
+ done
+ if [ -n "$umount" ]; then
+ umount "$umount" >/dev/null 2>&1
+ fi
+ exit $xit
+' 0
+
+if [ ! -b "$p_blockdev" ]; then
+ loop=",loop"
+fi
+
+if [ -n "$p_blockdev" ]; then
+ umount="$p_mountpoint"
+ mount -rt "$p_fstype" -o nosuid,nodev${loop} "$p_blockdev" "$p_mountpoint"
+fi
+
+updatetype=update
+
+if [ -z "$p_multi" ]; then
+ exit 1
+fi
+
+for f in main ctb nf lcl; do
+ eval 'this_packages=$p_'$f'_packages'
+ case "$this_packages" in
+ '')
+ continue
+ ;;
+ scan)
+ eval 'this_binary=$p_'$f'_binary'
+ if [ -z "$this_binary" ]; then
+ continue
+ fi
+ if [ "$updatetype" = update ]; then
+ dpkg --clear-avail
+ updatetype=merge
+ fi
+ echo Running dpkg --record-avail -R "$p_mountpoint$this_binary"
+ dpkg --record-avail -R "$p_mountpoint$this_binary"
+ ;;
+ *)
+ packagesfile="$p_mountpoint$this_packages"
+ case "$packagesfile" in
+ *.gz)
+ echo -n "Uncompressing $packagesfile ... "
+ zcat <"$packagesfile" >packages-$f
+ echo done.
+ dpkg --$updatetype-avail packages-$f
+ updatetype=merge
+ ;;
+ '')
+ ;;
+ *)
+ dpkg --$updatetype-avail "$packagesfile"
+ updatetype=merge
+ ;;
+ esac
+ ;;
+ esac
+done
+
+cp -f $vardir/available $vardir/methods/$method
+
+echo -n 'Update OK. Hit RETURN. '
+read response
+
+xit=0