[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#724931: Final? patch for bug #724931



Control: retitle -1 ISO loopback support for Debian installer
Control: affects -1 + cdrom-detect + apt-setup

Hi,

I further improved the patch by solving three problems and merging with the second patch from Ian.

First the solved problems:
 * Filesystem support:
On 06.10.2013 04:06, Andreas Cadhalpun wrote:
> * Added support for kfreebsd/hurd and any filesystem by using blkid
> to detect the filesystem of the device to be mounted.
While this is theoretically true, practically it is not, because not all filesystem drivers are included in the initrd. For example neither the ntfs nor the ext4 driver are included. For this patch to be useful, it has to be possible to loopmount from USB or hard disk. Therefore I suggest to include (in addition to the loop-module) the following modules (I updated the Apply_Patches.sh script accordingly):
  Highly recommended filesystem drivers:
     * ext2/ext3/ext4 (currently default Debian file system)
     * ntfs (currently default Windows file system)
     * udf (probably the future of USB file systems)
    These together are about 450 kB.
  Optional filesystem drivers:
     * btrfs
     * jfs
     * squashfs
     * xfs
    These together are about 650 kB.
Adding all of them to both initrd's makes the ISO approximately 2 MB larger, which should be no problem.

* aspell fails to install when using CD-set: This was due to the following code in 41cdset:
$logoutput $chroot $ROOT apt-cdrom -d $mount_point  add \
			   -o Dir::Etc::SourceList=/dev/null \
			   </dev/null;
I used /dev/null as argument for Dir::Etc::SourceList since the returned list is not used and I thought it would simply do nothing, but apparently it breaks the system somehow. Changing /dev/null to $tmp there and afterwards removing the $tmp file resolved the problem.

* CD-set authentication issue: I checked using the ISO as 'deb file:' repositories in an installed system. There the CD-2 works without problems, but CD-1 complains, as it should, since it is modified. But this is no explanation of the inconsistent behaviour of apt during installation. Perhaps 'deb cdrom:' repositories do generally not get checked for a correctly signed Release.gpg, but an additional 'deb file:' triggers a check? As a workaround for this problem, I changed the 'deb file:' entries to 'deb [ trusted=yes ] file:'. This should not be a security problem, since, when the checksum of the ISO is identical to the downloaded signed one, the user can be sure of the integrity of all software on the ISO. If it is not (or the user does not check) anything could be on the ISO anyway. Since the [ trusted=yes ] flag does no harm, I included it in this patch (if it works with an officially signed CD-1 without this flag, then it can be removed).

Furthermore I noticed, that the loopback.cfg I uploaded utilized 'loopback=' instead of 'loopmount=', which I corrected now. I testet, that grub2 can load it with e.g.:
menuentry "Debian Testing netinstall loopback (amd64)" {
	set gfxpayload=auto
	set iso_path="/ISO/debian-testing-amd64-netinst-loopmount.iso"
	export iso_path
	boot_options=locale=de_DE.UTF-8
	export boot_options
	loopback loop $iso_path
	set root=(loop)
	configfile /boot/grub/loopback.cfg
	loopback -d loop
}

The Apply_Patches.sh script now uses xorriso and produces isohybrid ISOs that can be directly dd'ed to an USB stick. I checked, and this still works, at least for the debian-7.1.0-amd64-CD-1.iso (though the installer does not use the native resolution of the display).

I tested this patch with all the following ISOs loopmounted using loopback.cfg from an USB with UDF file system and it seems to work perfectly:
 * debian-7.1.0-amd64-netinst.iso
 * debian-7.1.0-i386-netinst.iso
 * debian-7.1.0-amd64-CD-1.iso
 * debian-7.1.0-amd64-CD-2.iso (+)
 * debian-7.1.0-amd64-CD-3.iso (+)
 * debian-7.1.0-amd64-DVD-1.iso
 * debian-7.1.0-amd64-DVD-2.iso (+)
(+): Not modified, just copied to the folder of the first ISO in the set.
I did not inclued the testing ISOs in that list, although the patch seems to work there as well, because the testing ISOs are currently in no good shape (e.g. bug #725714).


On 06.10.2013 15:04, ian_bruce@fastmail.net wrote:
> I think the problem is related to this bug:
>
> http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=608201
I haven't noticed bug #608201, but indeed this is related.

> I have therefore adopted the (partial?) solution which was applied in
> that case, which is that ISO images which are found somewhere other
> than an actual CD, do not get included in "sources.list".
I understand the solution differently: The ISOs get included in the sources.list, but for some reason I don't know, the default behaviour of '40cdrom' is to unmount all CDs/ISOs and let 'apt-cdrom add' mount them again. (This is strange, since CD sets are handled in 41cdset and not in 40cdrom.) Because 'apt-cdrom add' does detect only CDs, not USB-HDD nor isohybird USBs nor loopmounted ISOs, this default behaviour has to be changed in those cases. The choosen method in bug #608201 was to export from 'cdrom-detect', whether it is an isohybrid or USB/USB-HDD and then from this determine in '40cdrom', whether or not the device is detectable by 'apt-cdrom add', i.e. is an actual disk in a drive. This is rather complicated, so I moved the determination of mountability to 'cdrom-detect' and exported this information for '40cdrom'. (Since I don't know, if the isohybrid/USB-HDD information is needed anywhere else, I still export that.)

> If a better solution is developed sometime later for those
> situations, it should apply to the loopmount case as well.
From my point of view, it should work if '40cdrom' just never unmounts anything and 'apt-cdrom add' is never allowed to mount anything, which would eliminate the need for exporting this information from 'cdrom-detect' to '40cdrom'.


> Two patchfiles are attached: a slightly altered one for
> "cdrom-detect", and a new one for "apt-setup". I haven't actually
> tested the latter, because I'm working with the "netinst" ISO, which > doesn't seem to include that package.
The debian-7.1.0-amd64-netinst.iso contains the relevant files in:
/pool/main/a/apt-setup/apt-cdrom-setup_0.79_all.udeb


> It appears that your changes to that file are similar to mine;
> however, I think mine are preferable, in this regard:
>
> I see that you have copied (in this and several other places) this
> piece of code, for determining if a loop-mount is being used:
>
>      for arg in $(cat /proc/cmdline); do
>          case $arg in
>          loopmount=*)
>              LOOPMOUNT=${arg#loopmount=}
>              LOOPFILE=${LOOPMOUNT#*:}
>              [ "$LOOPFILE" != "$LOOPMOUNT" ] && LOOPDEV=${LOOPMOUNT%:*}
>              ;;
>          esac
>      done
>
> Based on my current patches, this is now unnecessary. Do this instead:
>
>      loopmount=$(db_getval cdrom-detect/cdrom_loopdev)
I actually thought about using debconf to export the 'loopmount' variable, but since I didn't know how it works, I decided to use the 'quick and dirty' approach, that I knew to work. Using db_set is surely better, but your implementation does not work. I checked the manual:
 http://manpages.ubuntu.com/manpages/lucid/en/man7/debconf-devel.7.html
One needs to create the appropriate templates in the cdrom-detect.templates file, which I added now (and also for cdrom_options and cdrom_mountable). Using loopdev instead of loopmount to determine, whether an ISO is mounted, is preferable, because even if the loopmount boot parameter is set, but the ISO could not be loaded and instead e.g. a CD is loaded, none of the loopmount specific changes in the code after cdrom-detect will be executed.

> I'm not sure if I understand this:
>
>      if [ "$ROOT" ] && [ "$LOOPMOUNT" ]; then
>          save_label
>      fi
>
> Does that mean that the ISO will be specified in "sources.list"?
No it does not. It just saves the label of the current CD for '41cdset', which needs to know this. (It probably would be better to use debconf here as well.)
The entry in sources.list is created with the following command:
$logoutput $chroot $ROOT apt-cdrom add \
   -o Dir::Etc::SourceList=$tmp \
   </dev/null; then
cat $ROOT$tmp >> $file
Note that these entries only get to the actual sources.list, if the script exits successfully and otherwise they are ignored.

> However, I did not see any benefit in your changes
> to "cdrom-detect.postinst".
Then let me explain them to you. The remaining differences between my latest patch and your second patch in cdrom-detect are: * I did not include the $DISTRIB_LABEL, because I don't know how to do it best, and it works fine without (although it perhaps has to check more devices). If it helps you, the actually used $DISTRIB_LABEL is included on the ISO: In the file .disk/mkisofs is the command, with which the ISO was created and the option -V 'Debian 7.1.0 amd64 1' produces the label.
  You commented it out with the note:
# this should wait for a proper solution for bug #608201
I see no connection to that bug, since that has nothing to do with the installer device not being found, but rather it not being included in the apt database.

In cdrom-detect.postinst:
* In my patch the filesystem of the device to be mounted is determined automatically. Ian wrote:
> It's easy enough for somebody to add the proper file system types for
> Hurd and FreeBSD.
But it is even easier not having to do so! (And if it is so easy, why didn't you do it?) Furthermore your implementation suggested, that ext4 was supported, which was not, because it was not in the initrd. With my patch any filesystem driver in the initrd can be used.

* I export cdrom_options from cdrom-detect, so that the 'loop' option is used later on, when necessary (in 40cdrom and 41cdset).

* Changed the log message, if the cd mount fails, to give $loopdev${device#/loop} as device.

* Changed the log message from 'removable devices' to 'CD/maybe-usb-floppy devices', because USB sticks are commonly referred to as removable devices as well, but not included in the devices here.

* Changed an if statement, so that the CD/USB-HDD/isohybrid detection is executed, when loop-mounting the ISO fails. A 'break' prevents this, when the loop-mounting was successful.

* Unmount /loop before trying to mount an ISO to it, because it is possible that the user selects cdrom-detect a second time, which would lead to an error, if loop was already mounted in the first time.

* Changed the if-clause to determine which devices to look for to a for loop over $dev_given "usb-partition" "cd" "partition", which is better for two reasons: - The most likely devices (given device, usb devices) are looked at first. - If a $LOOPDEV is given, but no such device can be mounted, then the other devices are tried as well.

* Added log messages with $device and $fstype, before a device is mounted, since this information is most useful, if the mount fails, so a message after successful mounting is not enough.

* Do the cd_mountable determination in cdrom-detect and export the value via debconf.

* Added source code comments, harmonised formatting and removed trailing whitespaces.

* Added cdrom-detect/cdrom_options (for load-install-cd, 40cdrom, 41cdsest), cdrom-detect/cdrom_loopdev (for 40cdrom, 41cdset) and cdrom-detect/cdrom_mountable (for 40cdrom) to the cdrom-detect.templates file.


That being said, I think you agree, that this patch is ready to be included in the Debian installer, because no known problems exist, and it is tested quite thoroughly.

Best regards,
Andreas


Attachment: Apply-Patches.sh
Description: application/shellscript

diff -rupN apt-cdrom-setup.orig/usr/bin/load-install-cd apt-cdrom-setup/usr/bin/load-install-cd
--- apt-cdrom-setup.orig/usr/bin/load-install-cd	2011-03-23 03:00:10.000000000 +0100
+++ apt-cdrom-setup/usr/bin/load-install-cd	2013-10-07 11:45:30.503614305 +0200
@@ -10,6 +10,13 @@ ROOT="$1"
 
 logoutput="log-output -t load-install-cd"
 
+# Why isn't this function, or something like it,
+# in /usr/share/debconf/confmodule ?
+db_getval()
+{
+	db_get "$1" && echo "$RET" || true
+}
+
 check_id() {
 	cd_ids=$(LC_ALL=C $logoutput --pass-stdout chroot $ROOT \
 		 apt-cdrom ident | grep "^Identifying" | cut -d" " -f2)
@@ -29,18 +36,9 @@ while ! check_id; do
 	db_go || exit 10
 done
 
-fs=iso9660
-if db_get cdrom-detect/cdrom_fs && [ "$RET" ]; then
-	fs="$RET"
-fi
-OS=$(udpkg --print-os)
-case "$OS" in
-	hurd)
-		OPTIONS=ro
-		;;
-	*)
-		OPTIONS=ro,exec
-		;;
-esac
+fs=$(db_getval cdrom-detect/cdrom_fs)
+[ "$fs" ] || fs=iso9660
+OPTIONS=$(db_getval cdrom-detect/cdrom_options)
+[ "$OPTIONS" ] || OPTIONS=ro,exec
 db_get cdrom-detect/cdrom_device
 $logoutput mount -t "$fs" -o $OPTIONS $RET /cdrom
diff -rupN apt-cdrom-setup.orig/usr/lib/apt-setup/generators/40cdrom apt-cdrom-setup/usr/lib/apt-setup/generators/40cdrom
--- apt-cdrom-setup.orig/usr/lib/apt-setup/generators/40cdrom	2013-05-12 12:49:10.000000000 +0200
+++ apt-cdrom-setup/usr/lib/apt-setup/generators/40cdrom	2013-10-07 20:57:39.524104750 +0200
@@ -10,7 +10,9 @@ if ! type chroot_cleanup_localmounts >/d
 	# Variant of chroot_cleanup that only cleans up chroot_setup's mounts.
 	chroot_cleanup_localmounts () {
 		rm -f /target/usr/sbin/policy-rc.d
-		mv /target/sbin/start-stop-daemon.REAL /target/sbin/start-stop-daemon
+		if [ -f /target/sbin/start-stop-daemon.REAL ]; then
+			mv /target/sbin/start-stop-daemon.REAL /target/sbin/start-stop-daemon
+		fi
 		if [ -x /target/sbin/initctl.REAL ]; then
 			mv /target/sbin/initctl.REAL /target/sbin/initctl
 		fi
@@ -40,32 +42,23 @@ if [ ! -s /cdrom/.disk/info ]; then
 	exit 0
 fi
 
-cd_mountable=1
-db_get cdrom-detect/hybrid || true
-if [ "$RET" = true ] || [ -d /hd-media ]; then
-	cd_mountable=""
-else
-	db_get cdrom-detect/usb-hdd || true
-	if [ "$RET" = true ]; then
-		cd_mountable=""
-	fi
-fi
+# Why isn't this function, or something like it,
+# in /usr/share/debconf/confmodule ?
+db_getval()
+{
+	db_get "$1" && echo "$RET" || true
+}
+
+# See whether the device is mountable
+cd_mountable=true
+cd_mountable=$(db_getval cdrom-detect/cdrom_mountable)
 
 remount_cd() {
-	if [ "$ROOT" ] && [ "$cd_mountable" ]; then
-		fs=iso9660
-		if db_get cdrom-detect/cdrom_fs && [ "$RET" ]; then
-			fs="$RET"
-		fi
-		OS=$(udpkg --print-os)
-		case "$OS" in
-			hurd)
-				OPTIONS=ro
-				;;
-			*)
-				OPTIONS=ro,exec
-				;;
-		esac
+	if [ "$ROOT" ] && [ $cd_mountable = true ]; then
+		fs=$(db_getval cdrom-detect/cdrom_fs)
+		[ "$fs" ] || fs=iso9660
+		OPTIONS=$(db_getval cdrom-detect/cdrom_options)
+		[ "$OPTIONS" ] || OPTIONS=ro,exec
 		db_get cdrom-detect/cdrom_device
 		$logoutput mount -t "$fs" -o $OPTIONS $RET /cdrom || true
 	fi
@@ -106,7 +99,7 @@ if [ "$ROOT" ]; then
 	chroot=chroot
 
 	# Allow apt-cdrom to manage mounting/unmounting CDs in /target
-	if [ "$cd_mountable" ]; then
+	if [ $cd_mountable = true ]; then
 		rm -f $ROOT/etc/apt/apt.conf.d/00NoMountCDROM
 
 		$logoutput umount /target/media/cdrom* || true
@@ -121,13 +114,17 @@ fi
 
 tmp=$($chroot $ROOT tempfile)
 
+# See whether /cdrom is a loopmounted ISO
+loopdev=$(db_getval cdrom-detect/cdrom_loopdev)
+
 # apt-cdrom can be interactive, avoid that
 if $logoutput $chroot $ROOT apt-cdrom add \
    -o Dir::Etc::SourceList=$tmp \
    </dev/null; then
 	cat $ROOT$tmp >> $file
 
-	if [ "$ROOT" ] && [ "$cd_mountable" ]; then
+	# Save the name of the CD to let the  CD-set detection know, what the original CD was.
+	if [ "$ROOT" ] && ([ $cd_mountable = true ] || [ "$loopdev" ]); then
 		save_label
 	fi
 else
diff -rupN apt-cdrom-setup.orig/usr/lib/apt-setup/generators/41cdset apt-cdrom-setup/usr/lib/apt-setup/generators/41cdset
--- apt-cdrom-setup.orig/usr/lib/apt-setup/generators/41cdset	2011-01-19 05:26:34.000000000 +0100
+++ apt-cdrom-setup/usr/lib/apt-setup/generators/41cdset	2013-10-08 10:25:41.142525153 +0200
@@ -4,17 +4,22 @@ set -e
 . /usr/share/debconf/confmodule
 . /lib/chroot-setup.sh
 
+log() {
+	logger -t apt-setup "$@"
+}
+
 # This code is copied from chroot-setup.sh, and is needed until after a d-i
 # release whose initrds contain a sufficiently new version of di-utils.
 if ! type chroot_cleanup_localmounts >/dev/null 2>&1; then
 	# Variant of chroot_cleanup that only cleans up chroot_setup's mounts.
 	chroot_cleanup_localmounts () {
 		rm -f /target/usr/sbin/policy-rc.d
-		mv /target/sbin/start-stop-daemon.REAL /target/sbin/start-stop-daemon
+		if [ -f /target/sbin/start-stop-daemon.REAL ]; then
+			mv /target/sbin/start-stop-daemon.REAL /target/sbin/start-stop-daemon
+		fi
 		if [ -x /target/sbin/initctl.REAL ]; then
 			mv /target/sbin/initctl.REAL /target/sbin/initctl
 		fi
-
 		# Undo the mounts done by the packages during installation.
 		# Reverse sorting to umount the deepest mount points first.
 		# Items with count of 1 are new.
@@ -40,6 +45,7 @@ fi
 # KDE/Xfce CDs and multi-arch DVDs have '/single' postfix in cd_type
 # bluray CDs have cd_type 'bluray'
 cd_type=$(cat /cdrom/.disk/cd_type)
+log "The disk type is: $cd_type"
 if [ "$cd_type" != full_cd ] && [ "$cd_type" != dvd ]; then
 	exit 0
 fi
@@ -55,6 +61,8 @@ if [ "$CATCHLOG" ]; then
 	logoutput="log-output -t apt-setup"
 fi
 
+log "Starting disk set detection"
+
 chroot=
 if [ "$ROOT" ]; then
 	chroot=chroot
@@ -75,6 +83,29 @@ fi
 tmp=$($chroot $ROOT tempfile)
 
 cd_label=$(tail -n1 /var/lib/install-cd.id)
+
+# Why isn't this function, or something like it,
+# in /usr/share/debconf/confmodule ?
+db_getval()
+{
+	db_get "$1" && echo "$RET" || true
+}
+
+# See whether /cdrom is a loopmounted ISO
+loopdev=$(db_getval cdrom-detect/cdrom_loopdev)
+
+if [ "$loopdev" ]; then
+	run_count=0
+	max_run=0
+	# Load the mount parameters for the CD
+	CDFS=$(db_getval cdrom-detect/cdrom_fs)
+	[ "$CDFS" ] || CDFS=iso9660
+	OPTIONS=$(db_getval cdrom-detect/cdrom_options)
+	[ "$OPTIONS" ] || OPTIONS=ro,exec
+fi
+
+log "First installation disk: $cd_label"
+
 db_subst apt-setup/cdrom/set-first LABEL "$cd_label"
 db_input high apt-setup/cdrom/set-first || true
 if ! db_go; then
@@ -85,8 +116,96 @@ if ! db_go; then
 fi
 db_get apt-setup/cdrom/set-first
 
+log "Start detecting .."
+
 while [ "$RET" = true ]; do
-	cd_label=$(get_label)
+	cd_label=""
+	if [ "$loopdev" ]; then
+		if [ $run_count -eq 0 ]; then
+			log "Trying to find usable ISOs in the folder, where the boot ISO is..."
+			loopdir=$(db_getval cdrom-detect/cdrom_device)
+			ISOname=$(basename $loopdir)
+			loopdir=$(dirname $loopdir)
+			if [ "$cd_type" = "dvd" ]; then
+				# DVD
+				ISOstart=${filename%DVD-*}
+				ISOend=${filename#DVD-*}
+				ISOs=$(ls ${loopdir}/ | grep ${ISOstart}DVD-[^1].*[.]iso$)
+			elif [ "$cd_type" = "blueray" ]; then
+				# BD
+				ISOstart=${filename%BD-*}
+				ISOend=${filename#BD-*}
+				ISOs=$(ls ${loopdir}/ | grep ${ISOstart}BD-[^1].*[.]iso$)
+			else
+				# probably CD
+				ISOstart=${filename%CD-*}
+				ISOend=${filename#CD-*}
+				ISOs=$(ls ${loopdir}/ | grep ${ISOstart}CD-[^1].*[.]iso$)
+			fi
+			for iso in $ISOs; do
+				max_run=$(($max_run + 1))
+			done
+			log "Found $max_run ISO(s): $ISOs"
+		fi
+
+		try_iso=0
+		while [ $try_iso -eq 0 ]; do
+			if [ $run_count -lt $max_run ]; then
+				i=0
+				ISO=""
+				# select current ISO file
+				for isofile in $ISOs; do
+					if [ $i -eq $run_count ]; then
+						ISO=$isofile
+						break
+					fi
+					i=$(($i + 1))
+				done
+				j=1
+				# create mount point for the ISO
+				mount_point=/media/cdrom$j
+				while [ -d $ROOT$mount_point ]; do
+					j=$(($j + 1))
+					mount_point=/media/cdrom$j
+				done
+				mkdir $ROOT$mount_point
+
+				log "Try to loop mount file=$loopdir/$ISO, fstype=$CDFS to $ROOT$mount_point"
+				if mount -t $CDFS -o loop,$OPTIONS $loopdir/$ISO $ROOT$mount_point; then
+					log "CD-ROM mount succeeded: file=$loopdir/$ISO fstype=$CDFS"
+					if [ -e $ROOT$mount_point/.disk/info ]; then
+						CDNAME=$(cat $ROOT$mount_point/.disk/info | tr '"' '_')
+						log "Detected disk '$CDNAME'"
+						# Load the codename (e.g. jessie) from the database
+						db_get cdrom/codename
+						codename=$RET
+						RET=""
+						log "Detected codename: $codename"
+						try_iso=1
+					else
+						log "The disk in $loopdir/$ISO is not a Debian disk!"
+						umount $ROOT$mount_point 2>/dev/null || true
+						rmdir $ROOT$mount_point
+					fi
+				else
+					log "Mount failed: file=$loopdir/$ISO fstype=$CDFS"
+					umount $ROOT$mount_point 2>/dev/null || true
+					rmdir $ROOT$mount_point
+				fi
+			else
+				log "No more ISOs found"
+				break
+			fi
+			run_count=$(($run_count + 1))
+		done
+	fi
+	
+	if [ "$loopdev" ] && [ $try_iso -eq 1 ]; then
+		cd_label=$CDNAME
+	else
+		cd_label=$(get_label)
+	fi
+
 	# Hmm. The greps could fail if a label contains regexp control chars...
 	if [ "$cd_label" ] && \
 	   (grep "^deb cdrom:\[$cd_label\]" $file || \
@@ -94,20 +213,36 @@ while [ "$RET" = true ]; do
 		template=apt-setup/cdrom/set-double
 		db_subst $template LABEL "$cd_label"
 	else
-		# apt-cdrom can be interactive, avoid that
-		if $logoutput $chroot $ROOT apt-cdrom add \
-		   -o Dir::Etc::SourceList=$tmp \
-		   </dev/null; then
-			cat $ROOT$tmp >> $file
+		if [ "$loopdev" ] && [ $try_iso -eq 1 ]; then
+			# Add an entry for the mount point of the ISO
+			printf "\ndeb [ trusted=yes ] file:$mount_point $codename main" >> $file
+			log "added log entry: 'deb [ trusted=yes ] file:$mount_point $codename main'"
+
+			# Make apt aware of the file
+			$logoutput $chroot $ROOT apt-cdrom -d $mount_point  add \
+			   -o Dir::Etc::SourceList=$tmp \
+			   </dev/null;
+
+			rm -f $ROOT$tmp $ROOT$tmp~
 
-			# Label is assigned by apt-cdrom add, so get again
-			cd_label=$(get_label)
 			template=apt-setup/cdrom/set-next
 			db_subst $template LABEL "$cd_label"
 		else
-			template=apt-setup/cdrom/set-failed
+			# apt-cdrom can be interactive, avoid that
+			if $logoutput $chroot $ROOT apt-cdrom add \
+			   -o Dir::Etc::SourceList=$tmp \
+			   </dev/null; then
+				cat $ROOT$tmp >> $file
+
+				# Label is assigned by apt-cdrom add, so get again
+				cd_label=$(get_label)
+				template=apt-setup/cdrom/set-next
+				db_subst $template LABEL "$cd_label"
+			else
+				template=apt-setup/cdrom/set-failed
+			fi
+			rm -f $ROOT$tmp $ROOT$tmp~
 		fi
-		rm -f $ROOT$tmp $ROOT$tmp~
 	fi
 
 	db_input critical $template || true
diff -rupN apt-cdrom-setup.orig/usr/lib/finish-install.d/10apt-cdrom-setup apt-cdrom-setup/usr/lib/finish-install.d/10apt-cdrom-setup
--- apt-cdrom-setup.orig/usr/lib/finish-install.d/10apt-cdrom-setup	2011-01-19 05:26:34.000000000 +0100
+++ apt-cdrom-setup/usr/lib/finish-install.d/10apt-cdrom-setup	2013-10-08 19:07:26.177147843 +0200
@@ -1,6 +1,29 @@
 #! /bin/sh
 set -e
 
+. /usr/share/debconf/confmodule
+
+# See whether /cdrom is a loopmounted ISO
+db_get cdrom-detect/cdrom_loopdev || true
+loopdev="$RET"
+
+if [ "$loopdev" ]; then
+	# Remove additional CD-Set mount points
+	j=1
+	while [ -d /target/media/cdrom/$j ]; do
+		logger -t finish-install "unmount /target/media/cdrom/$j"
+		umount /target/media/cdrom/$j 2>/dev/null || true
+		rmdir /target/media/cdrom/$j
+		j=$(($j + 1))
+	done
+
+	if grep -q "^deb[^:]* file:" /target/etc/apt/sources.list; then
+		logger -t finish-install "Removing additional ISOs from sources.list"
+		sed -i "s/^deb[^:]* file:.*//g" /target/etc/apt/sources.list
+	fi
+	log-output -t finish-install chroot /target apt-get update
+fi
+
 # Disable netinst CD image in sources.list if any other sources are present
 if [ -e /cdrom/.disk/base_installable ] && \
    [ -e /cdrom/.disk/cd_type ] && \
diff -rupN debian-testing-amd64-netinst.orig/bin/check-missing-firmware debian-testing-amd64-netinst/bin/check-missing-firmware
--- debian-testing-amd64-netinst.orig/bin/check-missing-firmware	2013-08-16 15:10:00.000000000 +0200
+++ debian-testing-amd64-netinst/bin/check-missing-firmware	2013-10-07 17:42:12.120620713 +0200
@@ -246,6 +246,15 @@ check_for_firmware() {
 }
 
 while check_missing && ask_load_firmware; do
+	# If LOOPMOUNT is used, check the (busy) device from which the ISO is loaded
+	db_get cdrom-detect/cdrom_loopdev || true
+	if [ "$RET" ]; then
+		log "Check on /loop for firmware"
+		if [ -d /loop/firmware ]; then
+			check_for_firmware /loop/firmware/*.deb /loop/firmware/*.udeb
+		fi
+	fi
+
 	# first, check if needed firmware (u)debs are available on the
 	# PXE initrd or the installation CD.
 	if [ -d /firmware ]; then
diff -rupN debian-testing-amd64-netinst.orig/var/lib/dpkg/info/cdrom-detect.postinst debian-testing-amd64-netinst/var/lib/dpkg/info/cdrom-detect.postinst
--- debian-testing-amd64-netinst.orig/var/lib/dpkg/info/cdrom-detect.postinst	2013-08-17 11:10:50.000000000 +0200
+++ debian-testing-amd64-netinst/var/lib/dpkg/info/cdrom-detect.postinst	2013-10-07 14:26:02.946124525 +0200
@@ -1,4 +1,4 @@
-#! /bin/sh
+#!/bin/sh
 
 set -e
 . /usr/share/debconf/confmodule
@@ -14,26 +14,43 @@ fail() {
 	exit 1
 }
 
+list_devices_by_id()
+{
+	local dir disk="$(echo "$1" | sed 's/ /\\x20/g')"
+	for dir in /dev/disk/by-label /dev/disk/by-uuid ; do
+		[ -e ${dir}/${disk} ] && echo ${dir}/${disk} || true
+	done
+}
+
+get_fstype ()
+{
+	/sbin/blkid -s TYPE -o value $1 2>/dev/null
+}
+
 try_mount() {
 	local device=$1
 	local type=$2
+	local options=$3
+	local loopdev=$4
 
 	local ret=1
-	if mount -t $type -o $OPTIONS $device /cdrom; then
-		log "CD-ROM mount succeeded: device=$device fstype=$type"
+	if mount -o ${loopdev:+loop,}$options -t $type $device /cdrom; then
+		log "CD-ROM ${loopdev:+loop-}mount succeeded: device=$loopdev${device#/loop} fstype=$type"
 		if [ -e /cdrom/.disk/info ]; then
 			CDNAME=$(cat /cdrom/.disk/info)
 			log "Detected CD '$CDNAME'"
 			db_set cdrom-detect/cdrom_device $device
 			db_set cdrom-detect/cdrom_fs $type
+			db_set cdrom-detect/cdrom_options ${loopdev:+loop,}$options
+			db_set cdrom-detect/cdrom_loopdev $loopdev
 			ret=0
 		else
-			log "The CD in $device is not a Debian CD!"
+			log "The CD in $loopdev${device#/loop} is not a Debian CD!"
 			umount /cdrom 2>/dev/null || true
 			WRONG=1
 		fi
 	else
-		log "CD-ROM mount failed: device=$device fstype=$type"
+		log "CD-ROM ${loopdev:+loop-}mount failed: device=$loopdev${device#/loop} fstype=$type"
 	fi
 
 	return $ret
@@ -77,9 +94,8 @@ case "$OS" in
 	*)
 		log "Unknown OS '$OS', exiting"
 		exit 0
-		
 esac
- 
+
 # Is a cdrom already mounted? If so, assume it's the right one.
 mount | grep -q 'on /cdrom' && set_suite_and_codename && exit 0
 if [ -e /cdrom/.disk/info ]; then
@@ -95,42 +111,106 @@ log "Searching for Debian installation m
 
 mkdir /cdrom 2>/dev/null || true
 
+# Check whether the boot parameter 'loopmount=' is used
+for arg in $(cat /proc/cmdline); do
+	case $arg in
+	loopmount=*)
+		LOOPMOUNT=${arg#loopmount=}
+		LOOPFILE=${LOOPMOUNT#*:}
+		[ "$LOOPFILE" != "$LOOPMOUNT" ] && LOOPDEV=${LOOPMOUNT%:*}
+		;;
+	esac
+done
+
+if [ "$LOOPMOUNT" ]; then
+	# Create mount point for loop mount
+	mkdir /loop 2>/dev/null || true
+fi
+
 # Need to wait for the usb device scan to complete
 if [ "$OS" = "linux" ]; then
-  for count in 1 2 3 4 5 6 8 9 10; do
-    devices="$(list-devices cd; list-devices maybe-usb-floppy)"
-    log "Devices: '$devices'"
-    if [ -n "$devices" ]; then
-      break 2
-    else
-      sleep 1
-    fi
-  done
+	for count in 1 2 3 4 5 6 8 9 10; do
+		devices="$(list-devices cd; list-devices maybe-usb-floppy)"
+		log "CD/maybe-usb-floppy devices: '$devices'"
+		if [ "$devices" ]; then
+			break
+		else
+			sleep 1
+		fi
+	done
 fi
 
+# This is for apt-cdrom-setup, that needs to know, whether or not it should try to automatically (u)mount the device.
+cd_mountable=true
+
 while true; do
-	WRONG=
+	WRONG=''
+
+	if [ "$LOOPMOUNT" ]; then
+		mounted=0
+		log "Searching for Debian ISO: LOOPDEV='$LOOPDEV' LOOPFILE='$LOOPFILE'"
+		loopfile=/loop/${LOOPFILE#/}
+		log "Unmounting /loop just to be sure"
+		umount /loop 2>/dev/null || true
+
+		if [ "$LOOPDEV" ] ; then
+			dev_given="device_given"
+		else
+			dev_given=""
+		fi
+
+		# First look for the given device (if given) and then on USB devices, since the ISO is probably on them
+		for fs in $dev_given "usb-partition" "cd" "partition"; do
+			if [ "$fs" = "device_given" ]; then
+				devices="$(list_devices_by_id "$LOOPDEV")"
+			else
+				devices="$(list-devices $fs)"
+			fi
+			log "Trying loopmount ($fs) on '$devices' ..."
+			for loopdev in $devices; do
+				# Determine the filesystem of the device
+				LOOPFS=$(get_fstype "$loopdev")
+				# Mount the device and try to mount the ISO specified by 'loopmount='
+				log "Try to mount device=$loopdev fstype=$LOOPFS"
+				if mount -o $OPTIONS -t $LOOPFS $loopdev /loop; then
+					log "Try to loop mount file=$loopfile fstype=$CDFS"
+					if [ -f $loopfile ] && try_mount $loopfile $CDFS $OPTIONS $loopdev; then
+						mounted=1
+						cd_mountable=false
+						break 2
+					else
+						umount /loop
+					fi
+				fi
+			done
+		done
+		if [ $mounted -eq 1 ]; then
+			log "Succesfully mounted the ISO: no need to check further devices"
+			break
+		fi
+	fi
 
 	devices="$(list-devices cd; list-devices maybe-usb-floppy)"
 	for device in $devices; do
-		if try_mount $device $CDFS; then
+		if try_mount $device $CDFS $OPTIONS; then
 			break 2
 		fi
 	done
-	
+
 	devices="$(list-devices usb-partition)"
 	for device in $devices; do
-		if try_mount $device $CDFS; then
+		if try_mount $device $CDFS $OPTIONS; then
 			db_set cdrom-detect/hybrid true
+			cd_mountable=false
 			break 2
 		fi
-		if try_mount $device $FATFS; then
+		if try_mount $device $FATFS $OPTIONS; then
 			db_set cdrom-detect/usb-hdd true
+			cd_mountable=false
 			break 2
 		fi
 	done
 
-
 	if [ "$WRONG" ]; then
 		db_input critical cdrom-detect/wrong-cd || [ $? -eq 30 ]
 		db_go
@@ -138,7 +218,7 @@ while true; do
 	fi
 
 	# If a device was detected but the mount failed, ask for the CD.
-	if [ -n "$devices" ]; then
+	if [ "$devices" ]; then
 		db_input critical cdrom-detect/retry || [ $? -eq 30 ]
 		db_go
 		db_get cdrom-detect/retry
@@ -150,7 +230,7 @@ while true; do
 			fail
 		fi
 	fi
- 
+
 	# If no device was detected, perhaps a driver floppy is needed.
 	if [ -e /usr/lib/debian-installer/retriever/media-retriever ]; then
 		db_input critical cdrom-detect/load_media
@@ -162,7 +242,7 @@ while true; do
 			continue
 		fi
 	fi
-    
+
 	# Otherwise manual configuration may be needed
 	db_input critical cdrom-detect/manual_config || [ $? -eq 30 ]
 	db_go
@@ -266,4 +346,12 @@ else
 	anna-install $RET-support || true
 fi
 
+# Check for hd-media folder, which implies that it is not booted from CD.
+if [ -d /hd-media ]; then
+	cd_mountable=false
+fi
+
+# This is for apt-cdrom-setup, that needs to know, whether or not it should try to automatically (u)mount the device.
+db_set cdrom-detect/cdrom_mountable $cd_mountable
+
 exit 0
diff -rupN debian-testing-amd64-netinst.orig/var/lib/dpkg/info/cdrom-detect.templates debian-testing-amd64-netinst/var/lib/dpkg/info/cdrom-detect.templates
--- debian-testing-amd64-netinst.orig/var/lib/dpkg/info/cdrom-detect.templates	2013-10-07 02:06:30.000000000 +0200
+++ debian-testing-amd64-netinst/var/lib/dpkg/info/cdrom-detect.templates	2013-10-07 14:42:21.982081451 +0200
@@ -1097,6 +1097,12 @@ Default: iso9660
 Description: for internal use only
  File system used on cdrom-detect/cdrom_device.
 
+Template: cdrom-detect/cdrom_options
+Type: string
+Default: ro,exec
+Description: for internal use only
+ Options used to mount the cdrom-detect/cdrom_device.
+
 Template: cdrom-detect/hybrid
 Type: boolean
 Default: false
@@ -1109,6 +1115,17 @@ Default: false
 Description: for internal use only
  Set if the CD appears to be a live USB-HDD image.
 
+Template: cdrom-detect/cdrom_loopdev
+Type: string
+Description: for internal use only
+ Set if a ISO is loopmounted.
+
+Template: cdrom-detect/cdrom_mountable
+Type: boot
+Default: true
+Description: for internal use (communication with apt-cdrom-setup) only
+ This should be false, if the mounted device is not a removable disk in a drive.
+
 Template: cdrom-detect/scanning_progress_title
 Type: text
 Description: Scanning CD-ROM
menuentry 'Install' {
	set gfxpayload=auto
	linux	/install.amd/vmlinuz loopmount=$iso_path quiet $boot_options
	initrd	/install.amd/initrd.gz
}
menuentry 'Graphical install' {
	set gfxpayload=auto
	linux	/install.amd/vmlinuz loopmount=$iso_path quiet $boot_options
	initrd	/install.amd/gtk/initrd.gz
}
submenu 'Advanced options ...' {
	menuentry '... Expert install' {
		set gfxpayload=auto
		linux	/install.amd/vmlinuz priority=low loopmount=$iso_path $boot_options
		initrd	/install.amd/initrd.gz
	}
	menuentry '... Rescue mode' {
		set gfxpayload=auto
		linux	/install.amd/vmlinuz rescue/enable=true loopmount=$iso_path quiet $boot_options
		initrd	/install.amd/initrd.gz
	}
	menuentry '... Automated install' {
		set gfxpayload=auto
		linux	/install.amd/vmlinuz auto=true priority=critical loopmount=$iso_path quiet $boot_options
		initrd	/install.amd/initrd.gz
	}
	menuentry '... Graphical expert install' {
		set gfxpayload=auto
		linux	/install.amd/vmlinuz priority=low loopmount=$iso_path $boot_options
		initrd	/install.amd/gtk/initrd.gz
	}
	menuentry '... Graphical rescue mode' {
		set gfxpayload=auto
		linux	/install.amd/vmlinuz rescue/enable=true loopmount=$iso_path quiet $boot_options 
		initrd	/install.amd/gtk/initrd.gz
	}
	menuentry '... Graphical automated install' {
		set gfxpayload=auto
		linux	/install.amd/vmlinuz auto=true priority=critical loopmount=$iso_path quiet $boot_options
		initrd	/install.amd/gtk/initrd.gz
	}
	submenu '... Desktop environment menu ...' {
		submenu '... KDE desktop boot menu ...' {
			menuentry '... Install' {
				set gfxpayload=auto
				linux	/install.amd/vmlinuz desktop=kde loopmount=$iso_path quiet $boot_options
				initrd	/install.amd/initrd.gz
			}
			menuentry '... Graphical install' {
				set gfxpayload=auto
				linux	/install.amd/vmlinuz desktop=kde loopmount=$iso_path quiet $boot_options
				initrd	/install.amd/gtk/initrd.gz
			}
			submenu '... KDE advanced options ...' {
				menuentry '... Expert install' {
					set gfxpayload=auto
					linux	/install.amd/vmlinuz desktop=kde priority=low loopmount=$iso_path $boot_options
					initrd	/install.amd/initrd.gz
				}
				menuentry '... Automated install' {
					set gfxpayload=auto
					linux	/install.amd/vmlinuz desktop=kde auto=true priority=critical loopmount=$iso_path quiet $boot_options
					initrd	/install.amd/initrd.gz
				}
				menuentry '... Graphical expert install' {
					set gfxpayload=auto
					linux	/install.amd/vmlinuz desktop=kde priority=low video=vesa:ywrap,mtrr loopmount=$iso_path $boot_options
					initrd	/install.amd/gtk/initrd.gz
				}
				menuentry '... Graphical automated install' {
					set gfxpayload=auto
					linux	/install.amd/vmlinuz desktop=kde auto=true priority=critical loopmount=$iso_path quiet $boot_options
					initrd	/install.amd/gtk/initrd.gz
				}
			}
		}
		submenu '... LXDE desktop boot menu ...' {
			menuentry '... Install' {
					set gfxpayload=auto
				linux	/install.amd/vmlinuz desktop=lxde loopmount=$iso_path quiet $boot_options
				initrd	/install.amd/initrd.gz
			}
			menuentry '... Graphical install' {
					set gfxpayload=auto
				linux	/install.amd/vmlinuz desktop=lxde loopmount=$iso_path quiet $boot_options
				initrd	/install.amd/gtk/initrd.gz
			}
			submenu '... LXDE advanced options ...' {
				menuentry '... Expert install' {
					set gfxpayload=auto
					linux	/install.amd/vmlinuz desktop=lxde priority=low loopmount=$iso_path $boot_options
					initrd	/install.amd/initrd.gz
				}
				menuentry '... Automated install' {
					set gfxpayload=auto
					linux	/install.amd/vmlinuz desktop=lxde auto=true priority=critical loopmount=$iso_path quiet $boot_options
					initrd	/install.amd/initrd.gz
				}
				menuentry '... Graphical expert install' {
					set gfxpayload=auto
					linux	/install.amd/vmlinuz desktop=lxde priority=low loopmount=$iso_path $boot_options
					initrd	/install.amd/gtk/initrd.gz
				}
				menuentry '... Graphical automated install' {
					set gfxpayload=auto
					linux	/install.amd/vmlinuz desktop=lxde auto=true priority=critical loopmount=$iso_path quiet $boot_options
					initrd	/install.amd/gtk/initrd.gz
				}
			}
		}
		submenu '... Xfce desktop boot menu ...' {
			menuentry '... Install' {
					set gfxpayload=auto
				linux	/install.amd/vmlinuz desktop=xfce loopmount=$iso_path quiet $boot_options
				initrd	/install.amd/initrd.gz
			}
			menuentry '... Graphical install' {
					set gfxpayload=auto
				linux	/install.amd/vmlinuz desktop=xfce loopmount=$iso_path quiet $boot_options
				initrd	/install.amd/gtk/initrd.gz
			}
			submenu '... Xfce advanced options ...' {
				menuentry '... Expert install' {
					set gfxpayload=auto
					linux	/install.amd/vmlinuz desktop=xfce priority=low loopmount=$iso_path $boot_options
					initrd	/install.amd/initrd.gz
				}
				menuentry '... Automated install' {
					set gfxpayload=auto
					linux	/install.amd/vmlinuz desktop=xfce auto=true priority=critical loopmount=$iso_path quiet $boot_options
					initrd	/install.amd/initrd.gz
				}
				menuentry '... Graphical expert install' {
					set gfxpayload=auto
					linux	/install.amd/vmlinuz desktop=xfce priority=low loopmount=$iso_path $boot_options
					initrd	/install.amd/gtk/initrd.gz
				}
				menuentry '... Graphical automated install' {
					set background_color=black
					linux	/install.amd/vmlinuz desktop=xfce auto=true priority=critical loopmount=$iso_path quiet $boot_options
					initrd	/install.amd/gtk/initrd.gz
				}
			}
		}
	}
}
menuentry 'Install with speech synthesis' {
	set gfxpayload=auto
	linux	/install.amd/vmlinuz speakup.synth=soft loopmount=$iso_path quiet $boot_options
	initrd	/install.amd/gtk/initrd.gz
}

Reply to: