376 lines
8.5 KiB
Bash
Executable File
376 lines
8.5 KiB
Bash
Executable File
#! /bin/sh
|
|
|
|
. /lib/partman/lib/base.sh
|
|
. /lib/partman/lib/resize.sh
|
|
. /lib/partman/lib/recipes.sh
|
|
|
|
# busybox wants mount -o move; util-linux wants mount --move. Sigh.
|
|
if [ -d /lib/debian-installer ]; then
|
|
mount_move='-o move'
|
|
else
|
|
mount_move='--move'
|
|
fi
|
|
|
|
modprobe loop >/dev/null 2>&1 || true
|
|
|
|
# Set up working directory.
|
|
|
|
if type mktemp >/dev/null 2>&1; then
|
|
recipe_dir="$(mktemp -d /tmp/partman-auto-loop.XXXXXX)"
|
|
trap "rm -rf $recipe_dir" EXIT HUP INT QUIT TERM
|
|
else
|
|
recipe_dir=/tmp
|
|
fi
|
|
|
|
# Fetch parameters.
|
|
|
|
disk="$1"
|
|
|
|
cd $disk
|
|
|
|
if ! db_get partman-auto-loop/partition || [ -z "$RET" ]; then
|
|
logger -t partman-auto-loop "Error: No partition number specified in partman-auto-loop/partition"
|
|
exit 1
|
|
fi
|
|
partition="$RET"
|
|
|
|
if ! db_get partman-auto-loop/recipe || [ -z "$RET" ]; then
|
|
logger -t partman-auto-loop "Error: No recipe specified in partman-auto-loop/recipe"
|
|
exit 1
|
|
fi
|
|
recipe="$RET"
|
|
echo "$recipe" >"$recipe_dir/loop_recipe"
|
|
|
|
# Find the requested partition.
|
|
|
|
db_progress START 0 5 partman-auto/text/automatically_partition
|
|
db_progress INFO partman-auto/progress/info
|
|
|
|
partition_id=
|
|
partition_fs=
|
|
open_dialog PARTITIONS
|
|
while { read_line num id size type fs path name; [ "$id" ]; }; do
|
|
if [ "$num" = "$partition" ]; then
|
|
partition_id="$id"
|
|
partition_fs="$fs"
|
|
# go ahead and read all remaining input
|
|
fi
|
|
done
|
|
close_dialog
|
|
if [ -z "$partition_id" ]; then
|
|
logger -t partman-auto-loop "Error: Partition number $partition not found in $disk"
|
|
exit 1
|
|
fi
|
|
|
|
# Set up the requested partition in partman.
|
|
|
|
existing=no
|
|
for j in $(
|
|
for i in /lib/partman/valid_filesystems/*; do
|
|
[ -x $i ] || continue
|
|
$i $disk $partition_id existing
|
|
done
|
|
); do
|
|
if [ "$j" = "$partition_fs" ]; then
|
|
existing=yes
|
|
fi
|
|
done
|
|
|
|
if [ "$existing" = no ]; then
|
|
logger -t partman-auto-loop "Error: No filesystem on $disk/$partition_id"
|
|
exit 1
|
|
fi
|
|
|
|
echo keep >$partition_id/method
|
|
rm -f $partition_id/format
|
|
>$partition_id/use_filesystem
|
|
echo $partition_fs >$partition_id/filesystem
|
|
mkdir -p $partition_id/options
|
|
echo / >$partition_id/mountpoint
|
|
update_partition $disk $partition_id
|
|
|
|
# Is there enough space to perform the recipe?
|
|
|
|
dev="$disk"
|
|
oldid="$partition_id"
|
|
|
|
recipe_new=
|
|
firstword=
|
|
imagepaths=
|
|
for word in $(cat "$recipe_dir/loop_recipe"); do
|
|
case $word in
|
|
.)
|
|
recipe_new="${recipe_new:+$recipe_new }\$imagepath{ $firstword } $word"
|
|
firstword=
|
|
;;
|
|
*)
|
|
if [ "$firstword" ]; then
|
|
recipe_new="${recipe_new:+$recipe_new }$word"
|
|
else
|
|
firstword="$word"
|
|
imagepaths="${imagepaths:+$imagepaths }$word"
|
|
fi
|
|
;;
|
|
esac
|
|
done
|
|
echo "$recipe_new" >"$recipe_dir/loop_recipe_new"
|
|
decode_recipe "$recipe_dir/loop_recipe_new" loop
|
|
|
|
db_progress STEP 1
|
|
|
|
fstab="$(
|
|
for i in /lib/partman/fstab.d/*; do
|
|
[ -x "$i" ] || continue
|
|
$i
|
|
done |
|
|
while read fs mp type options dump pass; do
|
|
case $mp in
|
|
(/)
|
|
echo $fs $mp $type $options $dump $pass
|
|
;;
|
|
esac
|
|
done
|
|
)"
|
|
|
|
if [ -z "$fstab" ]; then
|
|
logger -t partman-auto-loop "Error: No fstab output for $disk/$partition_id"
|
|
exit 1
|
|
fi
|
|
|
|
mkdir -p /target
|
|
|
|
mountpoint="$(grep "^${fstab%% *} [^ ]* [^ ]* [^ ]*rw" /proc/mounts | cut -d ' ' -f2 | head -n1)" || mountpoint=
|
|
if [ "$mountpoint" = /target ]; then
|
|
# nothing to do
|
|
:
|
|
elif [ "$mountpoint" ]; then
|
|
if ! mount $mount_move "$mountpoint" /target; then
|
|
logger -t partman-auto-loop "Error: Failed to move $mountpoint to /target"
|
|
exit 1
|
|
fi
|
|
unmount_cmd='umount /target'
|
|
else
|
|
for m in /lib/partman/mount.d/*; do
|
|
[ -x "$m" ] || continue
|
|
|
|
unmount_cmd="$($m "$fstab")"
|
|
if [ "$?" = 0 ]; then
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
if [ -d /run ]; then
|
|
mkdir -p /run/sendsigs.omit.d
|
|
pidof mount.ntfs >> /run/sendsigs.omit.d/ntfs-3g
|
|
pidof mount.ntfs-3g >> /run/sendsigs.omit.d/ntfs-3g
|
|
fi
|
|
|
|
# TODO: handle errors if no mount succeeded
|
|
mkdir -p /host
|
|
mount $mount_move /target /host # TODO error handling
|
|
|
|
# Don't try to mount this again later.
|
|
rm -f $partition_id/mountpoint
|
|
|
|
# Ensure there is enough free space.
|
|
check_free_space=false
|
|
requires_disk_space(){
|
|
[ "$1" != 0 ] || return
|
|
path="$(echo "$*" | sed 's/.*\$imagepath{ *\([^ }]*\) *}.*/\1/')"
|
|
[ "$path" != "$*" ] || return
|
|
case $path in
|
|
/*) ;;
|
|
*) path="/$path" ;;
|
|
esac
|
|
[ -f "/host$path" ] && return
|
|
check_free_space=true
|
|
}
|
|
foreach_partition 'requires_disk_space $*'
|
|
|
|
# Skip resize_range check if images are already created.
|
|
if [ $check_free_space = true ]; then
|
|
case $partition_fs in
|
|
linux-swap|fat16|fat32|hfs|hfs+|hfsx)
|
|
get_resize_range
|
|
;;
|
|
ext2|ext3|ext4)
|
|
if ! search-path tune2fs; then
|
|
logger -t partman-auto-loop "Error: tune2fs not found"
|
|
exit 1
|
|
fi
|
|
if ! search-path resize2fs; then
|
|
logger -t partman-auto-loop "Error: resize2fs not found"
|
|
exit 1
|
|
fi
|
|
if ! get_ext2_resize_range; then
|
|
logger -t partman-auto-loop "Error: Failed to get ext2 resize range for $disk/$partition_id"
|
|
exit 1
|
|
fi
|
|
;;
|
|
ntfs)
|
|
if ! search-path ntfsresize; then
|
|
logger -t partman-auto-loop "Error: ntfsresize not found"
|
|
exit 1
|
|
fi
|
|
if ! get_ntfs_resize_range; then
|
|
db_input critical partman-auto-loop/unclean_ntfs || true
|
|
db_go || true
|
|
logger -t partman-auto-loop "Error: Failed to get NTFS resize range for $disk/$partition_id"
|
|
reboot
|
|
exit 1
|
|
fi
|
|
;;
|
|
*)
|
|
logger -t partman-auto-loop "Cannot calculate free space on filesystems of type $partition_fs"
|
|
exit 1
|
|
;;
|
|
esac
|
|
free_size="$(expr \( "$cursize" - "$minsize" \) \* 9 / 10)"
|
|
# convert to megabytes
|
|
free_size="$(expr 0000000"$free_size" : '0*\(..*\)......$')"
|
|
if [ $(min_size) -gt $free_size ]; then
|
|
logger -t partman-auto-loop "Error: partman-auto-loop/recipe too large ($(min_size) > $free_size)"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Ensure that no old loop images are present and mountable.
|
|
found_images=
|
|
mkdir -p /tmpmountpoint
|
|
for path in $imagepaths; do
|
|
case $path in
|
|
/*) ;;
|
|
*) path="/$path" ;;
|
|
esac
|
|
if [ -e "/host$path" ]; then
|
|
if mount -t auto -o loop,ro /host$path /tmpmountpoint 2>/dev/null 3>&-; then
|
|
found_images="${found_images:+$found_images }$path"
|
|
umount /tmpmountpoint || true
|
|
rmdir /tmpmountpoint || true
|
|
fi
|
|
fi
|
|
done
|
|
if [ "$found_images" ]; then
|
|
db_progress STOP
|
|
db_subst partman-auto-loop/unclean_host PARTITION "$partition"
|
|
db_subst partman-auto-loop/unclean_host DISK "$disk"
|
|
db_subst partman-auto-loop/unclean_host IMAGES "$found_images"
|
|
db_input critical partman-auto-loop/unclean_host || true
|
|
db_capb
|
|
db_go || true
|
|
db_capb backup
|
|
umount /host || true
|
|
exit 1
|
|
fi
|
|
|
|
db_progress STEP 1
|
|
|
|
expand_scheme
|
|
|
|
db_progress STEP 1
|
|
|
|
clean_method
|
|
|
|
db_progress STEP 1
|
|
|
|
setup_loop () {
|
|
[ "$1" != 0 ] || return
|
|
path="$(echo "$*" | sed 's/.*\$imagepath{ *\([^ }]*\) *}.*/\1/')"
|
|
[ "$path" != "$*" ] || return
|
|
|
|
case $path in
|
|
/*) ;;
|
|
*) path="/$path" ;;
|
|
esac
|
|
if [ ! -f "/host$path" ]; then
|
|
mkdir -p "/host${path%/*}"
|
|
if [ "$4" = "linux-swap" ]; then
|
|
# swap requires a file with no holes
|
|
dd if=/dev/zero of="/host$path" bs="1000000" count="$1"
|
|
else
|
|
dd if=/dev/zero of="/host$path" bs="1000000" seek="$1" count=0
|
|
fi
|
|
fi
|
|
if ! losetup -f "/host$path"; then
|
|
shift
|
|
continue
|
|
fi
|
|
if [ "$4" = linux-swap ]; then
|
|
loops="/host$path"
|
|
else
|
|
loops="$(echo /dev/loop* /dev/loop/*)"
|
|
fi
|
|
for loop in $loops; do
|
|
[ -e "$loop" ] || continue
|
|
case $loop in
|
|
/dev/loop*)
|
|
loopfile="$(losetup "$loop")" || continue
|
|
# The following works with both busybox's
|
|
# losetup and util-linux's losetup. Yes,
|
|
# this is ugly.
|
|
loopfile="$(echo "$loopfile" | sed 's,.*\(/host/[^)]*\).*,\1,')"
|
|
;;
|
|
*)
|
|
loopfile="$loop"
|
|
;;
|
|
esac
|
|
[ "$loopfile" = "/host$path" ] || continue
|
|
|
|
dirname="$(echo "$loop" | sed 's:/:=:g')"
|
|
dev="$DEVICES/$dirname"
|
|
|
|
rm -rf "$dev"
|
|
mkdir "$dev" || autopartitioning_failed
|
|
printf "%s" "$loop" >"$dev/device"
|
|
printf "%s" "$1" >"$dev/size"
|
|
echo "Loopback on $loopfile" >"$dev/model"
|
|
echo "$loopfile" >"$dev/loop"
|
|
|
|
cd "$dev"
|
|
open_dialog OPEN "$(cat "$dev/device")"
|
|
read_line response
|
|
close_dialog
|
|
if [ "$response" = failed ]; then
|
|
cd /
|
|
rm -rf "$dev"
|
|
autopartitioning_failed
|
|
fi
|
|
|
|
open_dialog NEW_LABEL loop
|
|
close_dialog
|
|
|
|
# find the free space
|
|
open_dialog PARTITIONS
|
|
free_space=
|
|
while { read_line num id size type fs path name; [ "$id" ]; }; do
|
|
if [ "$fs" = free ]; then
|
|
free_space=$id
|
|
free_size=$size
|
|
fi
|
|
done
|
|
close_dialog
|
|
|
|
# create partition in the free space
|
|
[ "$free_space" ] || autopartitioning_failed
|
|
open_dialog NEW_PARTITION primary $4 $free_space full ${1}000001
|
|
read_line num id size type fs path name
|
|
close_dialog
|
|
|
|
shift; shift; shift; shift
|
|
setup_partition $id $*
|
|
break
|
|
done
|
|
}
|
|
|
|
foreach_partition 'setup_loop $*'
|
|
|
|
db_progress STEP 1
|
|
|
|
update_all
|
|
|
|
apt-install lupin-support
|
|
|
|
db_progress STOP
|
|
|
|
exit 0
|