Parcourir la source

Integrate dpkg-multicd into dselect

The `multicd' package was initially written by Heiko Schlittermann
<heiko@lotte.sax.de> based on builtin access methods written by Ian
Jackson <ian@chiark.greenend.org.uk>.  The final packaging as well as
cleanups were made by Martin Schulze <joey@infodrom.north.de> who also
put this package together for the slink release (Debian GNU/Linux
2.1).

This commit includes the raw files as provided in version 0.21 of dpkg-multicd
(except for a few whitespaces cleanups).

The dpkg-scanpackages fork has been left out since the required features
have been merged in the official dpkg-scanpackages. Closes: #516631
Raphaël Hertzog il y a 17 ans
Parent
commit
fed6ba7830

+ 2 - 0
debian/changelog

@@ -49,6 +49,8 @@ dpkg (1.15.5) UNRELEASED; urgency=low
   * dpkg-scanpackages now supports a new --medium option as needed to
     generate Packages.cd file for consumption by the multicd dselect access
     method. Closes: #402527
+  * Integrate dpkg-multicd into dselect. Add the required Replaces and
+    Conflicts. The dpkg-scanpackages fork is dropped. Closes: #516631
 
   [ Updated dpkg translations ]
   * German (Sven Joachim).

+ 2 - 2
debian/control

@@ -58,8 +58,8 @@ Priority: optional
 Architecture: any
 Depends: ${shlibs:Depends}, dpkg (>= 1.13.1)
 Suggests: perl
-Conflicts: dpkg-ftp
-Replaces: dpkg (<< 1.10.3), dpkg-ftp
+Conflicts: dpkg-ftp, dpkg-multicd
+Replaces: dpkg (<< 1.10.3), dpkg-ftp, dpkg-multicd
 Description: Debian package management front-end
  dselect is a high-level interface for managing the installation and
  removal of Debian software packages.

+ 2 - 0
debian/copyright

@@ -13,6 +13,8 @@ Copyright © 1994-1999 Ian Jackson <ian@chiark.greenend.org.uk>
 Copyright © 1999 Richard Kettlewell <rjk@sfere.greenend.org.uk>
 Copyright © 1999 Ben Collins <bcollins@debian.org>
 Copyright © 1999 Roderick Shertler <roderick@argon.org>
+Copyright © 1998-1999 Martin Schulze <joey@infodrom.north.de>
+Copyright © 1998 Heiko Schlittermann <heiko@lotte.sax.de>
 Copyright © 1996-1998 Miquel van Smoorenburg <miquels@cistron.nl>
 Copyright © 1997-1998 Juho Vuori <javuori@cc.helsinki.fi>
 Copyright © 1997-1998 Charles Briscoe-Smith <cpbs@debian.org>

+ 1 - 0
debian/dpkg.docs

@@ -4,3 +4,4 @@ debian/usertags
 doc/README.api
 doc/README.feature-removal-schedule
 doc/triggers.txt
+dselect/methods/multicd/README.multicd

+ 12 - 2
dselect/methods/Makefile.am

@@ -12,7 +12,11 @@ nobase_dist_methods_DATA = \
 	floppy/desc.floppy \
 	ftp/names \
 	ftp/desc.ftp \
-	ftp/README.mirrors.txt
+	ftp/README.mirrors.txt \
+	multicd/names \
+	multicd/desc.multi_cd \
+	multicd/desc.multi_mount \
+	multicd/desc.multi_nfs
 
 nobase_dist_methods_SCRIPTS = \
 	disk/setup \
@@ -23,13 +27,19 @@ nobase_dist_methods_SCRIPTS = \
 	floppy/install \
 	ftp/setup \
 	ftp/update \
-	ftp/install
+	ftp/install \
+	multicd/setup \
+	multicd/update \
+	multicd/install
 
 perllibdir = $(PERL_LIBDIR)
 nobase_dist_perllib_DATA = Debian/Dselect/Ftp.pm
 
+EXTRA_DIST = multicd/README.multicd
+
 install-data-local:
 	$(mkdir_p) $(DESTDIR)$(admindir)/methods/mnt
 	$(mkdir_p) $(DESTDIR)$(admindir)/methods/disk
 	$(mkdir_p) $(DESTDIR)$(admindir)/methods/floppy
 	$(mkdir_p) $(DESTDIR)$(admindir)/methods/ftp
+	$(mkdir_p) $(DESTDIR)$(admindir)/methods/multicd

+ 131 - 0
dselect/methods/multicd/README.multicd

@@ -0,0 +1,131 @@
+Installation methods for multiple binary CDs
+--------------------------------------------
+
+ This package provides three new methods to be used within dselect in
+ order to access Debian binary packages stored across multiple binary CD
+ ROMs.  It will install itself into the methods directory from dselect
+ so the user will be able to use them immediately.
+
+ These are the three new methods:
+
+  . Multiple binary CD-ROMs
+
+  . Multiple binary CD-ROMs, accessed through NFS
+
+  . Multiple binary CD-ROMs, pre-mounted
+
+Acquiring package data
+---------------------
+
+ Since this method is derived from the `mounted' method the user is
+ able to access up to five binary directories within `dists/stable':
+
+  . main
+  . contrib
+  . non-free
+  . non-US
+  . local
+
+ The selected method will try to read the `Packages.cd' file from each
+ of these directories if it is available.
+
+Identifying the CD-ROM
+----------------------
+
+ A unique name is associated to each CD.  This name should correspond
+ with the label on the front of the CD.  The name is also available on
+ the CD, so the system can find out which CD is in the drive at any
+ time.
+
+Installing the files
+--------------------
+
+ At the beginning of the installation the `multicd' package will sort
+ the list of to-be-installed packages and install them CD by CD.  If a
+ different CD-ROM is required the user will be prompted to exchange
+ the CD-ROM.
+
+Preparing multiple binary CD-ROMs
+---------------------------------
+
+ Since the `multicd' methods need to know which packages are on which
+ CD-ROMs one cannot use regular `Packages' files.  An additional data
+ field "X-Medium:" is required.  The first CD-ROM from the set should
+ contain all `Packages.cd' files.  To be more convenient you should
+ include the `Packages.cd' files on all CD-ROMs.  This ensures that
+ you don't have to start with the first CD-ROM all the time.
+
+ Additionally the package needs to gain information which CD-ROM is
+ currently used.  Thus each CD-ROM contains the file `.disk/info'
+ which contains the symbolic name for the CD-ROM as specified by
+ "X-Medium:".
+
+ In order to be able to create the modified `Packages.cd' files, this
+ package installs a modified version of `dpkg-scanpackages' in
+ /usr/bin.  You'll need to specify the used medium with `-m medium'.
+
+ To split the `main' distribution into two CD-ROMs you'll 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.
+
+dpkg-scanpackages
+-----------------
+
+ This package provides an improved version of `dpkg-scanpackages'
+ which comes with the following additional features:
+
+  . It can read compressed overrides files
+
+  . Using `-m <medium>' you can tell the program to add the new data
+    field "X-Medium:" for each record in the output.
+
+ This version is installed using `dpkg-divert' which will disable the
+ original `dpkg-scanpackages' program.
+
+Sample Layout
+-------------
+
+ CD1 .disk/info = "Debian GNU/Linux binary-i386"
+     dists/stable/main/binary-all/
+                       binary-i386/Packages.cd.gz
+                       binary-i386/net/foo.deb
+                  contrib/binary-i386/Packages.cd.gz
+                  non-free/binary-i386/Packages.cd.gz
+                  non-US/binary-i386/Packages.cd.gz
+
+ CD2 .disk/info = "Debian GNU/Linux contrib-i386"
+     dists/stable/main/binary-i386/Packages.cd.gz
+                  contrib/binary-all/
+                          binary-i386/Packages.cd.gz
+                          binary-i386/net/foo.deb
+                  non-free/binary-i386/Packages.cd.gz
+                  non-US/binary-i386/Packages.cd.gz
+
+ CD3 .disk/info = "Debian GNU/Linux non-free-i386"
+     dists/stable/main/binary-i386/Packages.cd.gz
+                  contrib/binary-i386/Packages.cd.gz
+                  non-free/binary-all/
+                           binary-i386/Packages.cd.gz
+                           binary-i386/net/foo.deb
+                  non-US/binary-all/
+
+ To re-generate the Packages file you have to chdir into
+ `dists/stable/$part' and issue `dpkg-scanpackages' as follows.  It's
+ assumed that you regular compressed overrides files in
+ /pub/debian/indices.
+
+ CD1: dpkg-scanpackages -m "Debian GNU/Linux binary-i386" \
+        binary-i386 /pub/debian/indices/override.hamm.gz \
+        dists/stable/ > binary-i386/Packages
+
+ CD2: dpkg-scanpackages -m "Debian GNU/Linux contrib-i386" \
+        binary-i386 /pub/debian/indices/override.hamm.contrib.gz \
+        dists/stable/ > binary-i386/Packages
+
+ CD3: dpkg-scanpackages -m "Debian GNU/Linux non-free-i386" \
+        binary-i386 /pub/debian/indices/override.hamm.non-free.gz \
+        dists/stable/ > binary-i386/Packages
+
+Please direct comments to Martin Schulze <joey@infodrom.north.de>

+ 3 - 0
dselect/methods/multicd/desc.multi_cd

@@ -0,0 +1,3 @@
+Installation from a CD-ROM set containing a Debian distribution.  The
+CD-ROMs may be or not be mounted already and should contain a standard
+ISO9660 CD-ROM filesystem.

+ 12 - 0
dselect/methods/multicd/desc.multi_mount

@@ -0,0 +1,12 @@
+Installation from a pre-mounted directory with changing content.
+
+The directory contains the Packages.gz file from each distribution
+area being installed (usually main, contrib, non-free, local and
+eventually non-US) as well as an excerpt of the corresponding
+binary/*/*.deb files.
+
+The easiest way for them to get this is to make a (partial) copy of
+the distribution site's directory hierarchy, if possible.
+
+The contents of the mounted directory may change.  Thus it's possible
+to use this method for installations from images of a CDROM set.

+ 12 - 0
dselect/methods/multicd/desc.multi_nfs

@@ -0,0 +1,12 @@
+Installation across the network, from an NFS server which is not
+currently mounted.
+
+The server should contain the Packages.gz file from each distribution
+area being installed (usually main, contrib, non-free, local and
+eventually non-US) as well as the corresponding binary/*/*.deb files.
+
+The easiest way for them to get this is to make a (partial) copy of
+the distribution site's directory hierarchy, if possible.
+
+The contents of the mounted directory may change.  Thus it's possible
+to use this method for installations from a CDROM set.

+ 294 - 0
dselect/methods/multicd/install

@@ -0,0 +1,294 @@
+#!/bin/sh
+
+set -e
+vardir="$1"
+method=$2
+option=$3
+
+
+cd "$vardir/methods/$method"
+
+. ./shvar.$option
+
+
+#debug() { echo "DEBUG: $@"; }
+debug() { true; }
+iarch=`dpkg --print-installation-architecture`
+ismulti() { 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"`
+    else
+        if [ -f $1$2/.disk/info ]
+	then
+	    echo -n `head -1 "$1$2/.disk/info"`
+	else
+            echo -n 'Non-Debian disc'
+	fi
+    fi
+}
+
+xit=1
+
+do_umount() {
+	if [ "$method" = "multi_mount" ]
+	then
+		echo /bin/true
+		return
+	fi
+	if [ -n "$umount" ]; then
+		echo umount "$umount"
+		#">/dev/null" "2>&1"
+	fi
+}
+
+do_mount() {
+
+	if [ "$method" = "multi_mount" ]
+	then
+		echo /bin/true
+		return
+	fi
+
+	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
+
+	if [ -n "$p_nfs" ]
+	then
+		umount="$p_mountpoint"
+		echo mount -rt nfs "$p_nfs" -o nosuid,nodev "$p_mountpoint"\; umount="$p_mountpoint"
+	fi
+
+	#if [ -n "$p_multi" -a -n "$p_multi_contentsfile" ]; then
+		#echo "This is disk "
+		#echo "    "`getdisklabel "${p_mountpoint}" "${p_hierbase}"`
+	#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") || 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;
+		}
+		length($package) || die "internal error - no package";
+		@filename || die "internal error - no filename";
+		@filename==@msdosfilename || !@filename || !@msdosfilename ||
+			die "internal error - mismatch >@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,.*/,,;
+				defined($c= open(X,"-|")) ||
+					die "failed to fork for find: $!\n";
+				if (!$c) {
+					exec("find", length($binaryprefix)
+					     ? $binaryprefix : ".","-follow",
+					     "-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)) {
+				print STDERR "
+
+Oh dear, I need to install or upgrade $package, but I don'\''t see
+the appropriate file(s) anywhere.  I'\''m expecting version $version or
+later, as that is listed in the Packages.cd file.
+
+Perhaps you downloaded it with an unexpected name, or something.
+In any case, you must find the file(s) and then either place it with
+the correct filename(s) (as listed in the Packages.cd file or in
+/var/lib/dpkg/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/multicd/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, I need disc\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 tell me, if I should\n",
+				  "continue with the next CD. [Y/n]: ";
+			$ans = <STDIN>;
+			exit 1 if $ans =~ /^n/i;
+			$ouch = $?;
+		}
+	}
+
+	exit $ouch;
+
+' "$vardir" "$p_mountpoint" "$p_hierbase" "`do_mount`" "`do_umount`"
+
+
+echo -n 'Installation OK.  Hit RETURN.  '
+read response
+
+xit=0
+
+# vim:ts=4:sw=4:aw:ai:

+ 3 - 0
dselect/methods/multicd/names

@@ -0,0 +1,3 @@
+31 multi_cd Install from a CD-ROM set.
+36 multi_nfs Install from an NFS server (using the CD-ROM set) (not yet mounted).
+46 multi_mount Install from a mounted partition with changing contents.

+ 663 - 0
dselect/methods/multicd/setup

@@ -0,0 +1,663 @@
+#!/bin/sh
+
+set -e
+vardir="$1"
+method=$2
+option=$3
+
+test -d "$vardir/methods/$method" || mkdir "$vardir/methods/$method"
+cd "$vardir/methods/$method"
+tp=/tmp/ddm$$
+
+iarch=`dpkg --print-installation-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"`
+    else
+        if [ -f $1$2/.disk/info ]
+	then
+	    echo -n `head -1 "$1$2/.disk/info"`
+	else
+            echo -n 'Non-Debian disc'
+	fi
+    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"
+		if [ $option = multi_cd ]
+		then
+			fstype=iso9660
+		elif [ $option = harddisk2 ]
+		then
+			blockbase="`echo \"$tryblockdevice\" | sed -e 's/[0-9]\{1,\}$//'`"
+			set +e
+			echo -e "p\nq\n" | fdisk "$blockbase" 2>/dev/null >$tp.f
+			set -e
+			proposeddevice="$tryblockdevice" perl -ne '
+next unless /^ *Device +Boot +Begin +Start +End +Blocks +Id +System *$/i .. !/\S/;
+next unless s:^/\S+:: && $& eq $ENV{"proposeddevice"};
+next unless s/^ +(\* +)?\d+ +\d+ +\d+ +\d+\+? +//;
+next unless m/^([0-9a-f]{1,2}) /i;
+%types= ( "1","msdos", "4","msdos", "6","msdos", "7","hpfs", "80","minix",
+          "81","minix", "83","ext2" );
+print $types{$1}; exit(0);	' <$tp.f >$tp.m
+			defaultfstype="`cat $tp.m`"
+			if [ -n "$defaultfstype" ]
+			then
+				cat <<END
+The partition table for $blockbase claims that $tryblockdevice
+contains filesystem type $defaultfstype.
+END
+				if ! grep "	$defaultfstype$" /proc/filesystems >/dev/null
+				then
+					echo \
+	"Your kernel does not appear to support that filesystem type."
+					defaultfstype=""
+				fi
+			fi
+			echo -n "Supported filesystems: "
+			sed -e 's/^.*	/ /' /proc/filesystems | tr '\n' ' '
+			echo -n "
+Enter filesystem type (for $tryblockdevice) [$defaultfstype]:  "
+			read fstype
+			if [ -z "$fstype" ]
+			then
+				fstype="$defaultfstype"
+			fi
+		fi
+		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,nonus,nonusctb,nonusnf,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"
+	defaultnfsserver="$p_nfsserver"
+	defaultnfsrempath="$p_nfsrempath"
+	usedevel="$p_usedevel"
+fi
+
+if [ $option = multi_cd ]
+then
+	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 CD-ROMs (or other ISO9660 filesystems) are mounted:'
+			egrep '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 \
+	"I see a CD-ROM: $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 \
+	'I see that /dev/cdrom exists and is a block device.'
+			newdefaultdevice=/dev/cdrom
+		fi
+		getblockdev 'Insert the CD-ROM and enter the block device name'
+	fi
+fi
+
+if [ $option = multi_nfs ]
+then
+	mountpoint="$vardir/methods/mnt"
+	while [ -z "$nfsserver" ]
+	do
+		echo -n \
+"What is the name of the NFS server ? [$defaultnfsserver]  "
+		read response
+		if [ -z "$response" -a -n "$defaultnfsserver" ]
+		then
+			response="$defaultnfsserver"
+		fi
+		if [ -z "$response" ]; then continue; fi
+		if [ -x /usr/bin/rpcinfo ]
+		then
+			if rpcinfo -u "$response" mountd >/dev/null
+			then
+				nfsserver="$response"
+			else
+				echo "$response appears not to be an NFS server."
+			fi
+		elif [ -x /bin/ping ]
+		then
+			if ping -q -c 1 "$response" | grep -q ', 1 packets received'
+			then
+				nfsserver="$response"
+			else
+				echo "$response appears to be down or nonexistent."
+			fi
+		else
+			echo \
+"(I can't check that now because there is no /usr/bin/rpcinfo or /bin/ping.)"
+			nfsserver="$response"
+		fi
+	done
+	while [ -z "$nfsrempath" ]
+	do
+		echo -n "
+What is the pathname on the NFS server of the filesystem with
+the Debian files ? [$defaultnfsrempath]  "
+		read response
+		if [ -z "$response" -a -n "$defaultnfsrempath" ]
+		then
+			response="$defaultnfsrempath"
+		else
+			response="`echo \"$response\" | sed -e 's:/$::; s:^/*:/:'`"
+		fi
+		umount="$mountpoint"
+		if mount -rt nfs -o nosuid,nodev "$nfsserver:$response" "$mountpoint"
+		then
+			echo
+			nfsrempath="$response"
+		else
+			umount=""
+			echo \
+"Unable to mount NFS filesystem $nfsserver:$response."
+		fi
+	done
+	nfs="$nfsserver:$nfsrempath"
+fi
+
+if [ $option = harddisk2 ]
+then
+	set +e
+	echo -e 'p\nq\n' | fdisk /dev/hda 2>/dev/null >$tp.f
+	if [ $? != 0 ]
+	then
+		echo -e 'p\nq\n' | fdisk /dev/sda 2>/dev/null >$tp.f
+	fi
+	set -e
+	perl -ne '
+next unless /^ *Device +Boot +Begin +Start +End +Blocks +Id +System *$/i .. !/\S/;
+next unless / [146] +DOS \d+-bit \S+$/;
+next unless m:^/\S+:;
+print $&;		' <$tp.f >$tp.d
+	newdefaultdevice="`cat $tp.d`"
+	echo "
+I need to know which disk partition contains the distribution files;
+disk partitions are specified by the block device name in Linux."
+	if [ -n "$newdefaultdevice" ]
+	then
+		echo \
+"By the way, $newdefaultdevice looks like a DOS partition."
+	fi
+	getblockdev "Enter the partition's block device name"
+fi
+
+if [ -n "$mountpoint" ]
+then
+	# We must have $mountpoint
+	if [ $option = multi_cd ]
+	then
+		echo \
+'All directory names should be entered relative to the root of the CD-ROM.
+'
+	elif [ $option = multi_nfs ]
+	then
+		echo \
+"All directory names should be entered relative to the root of the NFS
+filesystem, ie relative to $nfsrempath on the server.
+"
+	else
+		echo \
+"All directory names should be entered relative to the root of the
+$fstype filesystem on $blockdevice.
+"
+	fi
+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
+
+	if [ $option = multi_cd ]
+	then
+		echo \
+"I would like to know where on the CD-ROM the top level of the Debian
+distribution is - this will usually contain the \`dists' directory.
+
+If the CD-ROM is badly organized and doesn't have a straightforward copy of
+the distribution you may answer \`none' and we'll go through the parts
+I need individually."
+	else
+		echo \
+"In order to make it easy for me to find the relevant files I'd ideally
+like to install from a straightforward copy of the Debian distribution.
+To use this I'll need to know where the top level of that copy of the
+distribution is - this directory usually contains the Packages-Master file.
+
+If you do not have a straightforward copy of the distribution available
+just answer \`none' and we'll go through the parts I need individually."
+	fi
+
+	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 I can't get the impression that you're using a multi-CD  set."
+		fi
+	fi
+
+	# at this point defhierbase is set if it looks plausible
+	# if `none' was entered, we assume a CD 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 multi-CD 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 multi CD 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 CD should contain all Packages.cd files but doesn't
+# need to contain the .deb files.
+#
+#  	if ! { find "$mountpoint$2" -follow -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 dir"
+
+	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 [ $option = multi_cd -a $2 = nf -a -z "$this_binary" ]
+	then
+		echo '
+Note: most CD-ROM distributions of Debian do not include programs
+available in the `non-free'\'' directory of the distribution site.
+This is because these programs have copyrights that prevent
+distribution for profit on a CD-ROM - ie they are not free software.
+If you wish to install these programs you'\''ll 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 dir. [$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
+		else
+			if [ -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
+		fi
+		while [ -z "$this_packages" ]
+		do
+			echo -n "
+I can't 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
+CD-ROMs.  Alternatively (and this will be rather slow) I can scan the
+packages in the distribution area - say \`scan' if you want me 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 nf "$distribution" "$p_nf_binary" "$p_nf_packages"
+find_area non-US/main nonus "$distribution" "$p_nonus_binary" "$p_nonus_packages"
+find_area non-US/contrib nonusctb "$distribution" "$p_nonusctb_binary" "$p_nonusctb_packages"
+find_area non-US/non-free nonusnf "$distribution" "$p_nonusnf_binary" "$p_nonusnf_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_nfsserver "$nfsserver"
+outputparam p_nfsrempath "$nfsrempath"
+outputparam p_nfs "$nfs"
+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_nf_packages "$nf_packages"
+outputparam p_nf_binary "$nf_binary"
+outputparam p_nf_disk "$nf_disk"
+outputparam p_nonus_binary "$nonus_binary"
+outputparam p_nonus_packages "$nonus_packages"
+outputparam p_nonus_disk "$nonus_disk"
+outputparam p_nonusctb_binary "$nonusctb_binary"
+outputparam p_nonusctb_packages "$nonusctb_packages"
+outputparam p_nonusctb_disk "$nonusctb_disk"
+outputparam p_nonusnf_binary "$nonusnf_binary"
+outputparam p_nonusnf_packages "$nonusnf_packages"
+outputparam p_nonusnf_disk "$nonusnf_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
+
+# vim:ts=4:sw=4:aw:ai:

+ 116 - 0
dselect/methods/multicd/update

@@ -0,0 +1,116 @@
+#!/bin/sh
+
+set -e
+vardir="$1"
+method=$2
+option=$3
+iarch=`dpkg --print-installation-architecture`
+
+cd "$vardir/methods/$method"
+
+. ./shvar.$option
+
+#debug() { echo "DEBUG: $@"; }
+debug() { true; }
+ismulti() { debug $1 $2; test -e "$1/.disk/info" || test -e "$1$2/.disk/info"; }
+
+packages=0
+for f in main ctb nf nonus nonusctb nonusnf 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 '
+	rm -f packages-{main,ctb,nf,nonus,nonusctb,nonusnf,lcl}
+	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
+
+if [ -n "$p_nfs" ]
+then
+	umount="$p_mountpoint"
+	mount -rt nfs "$p_nfs" -o nosuid,nodev "$p_mountpoint"
+fi
+
+updatetype=update
+
+if [ -z "$p_multi" ]; then
+	exit 1
+fi
+
+for f in main ctb nf nonus nonusctb nonusnf 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 | *.Z | *.GZ | *.z)
+			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
+
+dpkg --forget-old-unavail
+
+echo -n 'Update OK.  Hit RETURN.  '
+read response
+
+xit=0