#!/bin/sh . /lib/partman/lib/base.sh . /lib/partman/lib/resize.sh . /lib/partman/lib/auto-shared.sh ARCH="$(archdetect)" case $ARCH in armel/*) # Dual-booting on ARM is difficult for casual users exit 0 ;; esac bestfree=0 bestpart=none bestpath=none tmpfile="$(mktemp /tmp/partman-auto.XXXXXX)" trap "rm -f $tmpfile" EXIT HUP INT QUIT TERM # Count the number of primary and logical partitions. count_primary_logical () { local primaries=0 local logicals=0 while { read num oldid size type fs path name; [ "$oldid" ]; }; do case $fs in free) ;; *) case $type in primary) primaries="$(($primaries + 1))" ;; logical) logicals="$(($logicals + 1))" ;; esac ;; esac echo "$primaries $logicals" done | tail -n1 } # Filter a partition list to include only those entries which are already # part of an extended partition or which can be resized to provide # additional space in an extended partition. can_be_extended () { local previous= while { read num oldid size type fs path name; [ "$oldid" ]; }; do case $type in logical|pri/log) if [ "$previous" ]; then # If the previous partition can be resized, that will # create additional space at the end adjacent to this # partition. echo "$previous" previous= fi echo "$num $oldid $size $type $fs $path $name" ;; *) previous="$num $oldid $size $type $fs $path $name" ;; esac done } scan_disk () { local partitions uses_extended max_primary local primary_logical primaries logicals totalfree=0 diskfree=0 diskpart=none diskpath=none open_dialog PARTITIONS partitions="$(read_paragraph)" close_dialog open_dialog USES_EXTENDED read_line uses_extended close_dialog open_dialog GET_MAX_PRIMARY read_line max_primary close_dialog if [ -z "$max_primary" ]; then log "Unable to get maximum primary partition count on $dev" return fi # TODO: This should all be checked later to take account of recipes # other than the defaults for the supported Ubuntu architectures. if [ "$uses_extended" = yes ]; then primary_logical="$(echo "$partitions" | count_primary_logical)" if [ "$primary_logical" ]; then primaries="${primary_logical% *}" logicals="${primary_logical#* }" log "$primaries primary partitions, $logicals logical partitions" # If there are no logical partitions, then we will need a # primary partition slot to create an extended partition. if [ "$logicals" -eq 0 ] && \ [ "$primaries" -ge "$max_primary" ]; then log "Too many primary partitions already exist on $dev without an extended partition" return fi # If there is already an extended partition, then only consider # those partitions in which (after resizing) partitions can be # created sufficiently freely. if [ "$logicals" -ne 0 ]; then partitions="$(echo "$partitions" | can_be_extended)" log "filtered partition list:" log "$partitions" fi fi fi # Parts of the body of this while loop may use debconf, so we must not # interfere with stdin, hence the temporary file. echo "$partitions" >"$tmpfile" while { read num oldid size type fs path name <&9; [ "$oldid" ]; }; do case $fs in free) totalfree="$(expr "$totalfree" + "$size")" ;; linux-swap|fat32) get_resize_range if [ "$cursize" ] && [ "$minsize" ]; then thisfree="$(expr "$cursize" - "$minsize")" if longint_le $diskfree $thisfree; then diskfree=$thisfree diskpart=$dev//$oldid diskpath=$path fi fi ;; ext2|ext3|ext4) if ! type tune2fs >/dev/null 2>&1 || ! type resize2fs >/dev/null 2>&1; then continue fi check_virtual if [ "$virtual" = yes ]; then get_resize_range else get_real_resize_range "$oldid" "$fs" || continue fi if [ "$cursize" ] && [ "$minsize" ]; then thisfree="$(expr "$cursize" - "$minsize")" if longint_le $diskfree $thisfree; then diskfree=$thisfree diskpart=$dev//$oldid diskpath=$path fi fi ;; ntfs) if ! type ntfsresize >/dev/null 2>&1; then continue fi check_virtual if [ "$virtual" = yes ]; then get_resize_range else get_real_resize_range "$oldid" "$fs" || continue fi if [ "$cursize" ] && [ "$minsize" ]; then thisfree="$(expr "$cursize" - "$minsize")" if longint_le $diskfree $thisfree; then diskfree=$thisfree diskpart=$dev//$oldid diskpath=$path fi fi ;; esac done 9<"$tmpfile" } get_resize_use_free_on_dev() { cd $dev scan_disk log "dev: '$dev', totalfree: '$totalfree', diskfree: '$diskfree', diskpart: '$diskpart', diskpath: '$diskpath'" if longint_le "$bestfree" "$diskfree"; then bestfree="$diskfree" bestpart="$diskpart" bestpath="$diskpath" fi } dev="$1" if [ -z "$dev" ]; then DEVS="$(get_auto_disks)" IFS="$NL" for dev in $DEVS; do restore_ifs dev="${dev%$TAB*}" get_resize_use_free_on_dev IFS="$NL" done restore_ifs else get_resize_use_free_on_dev fi if [ -z "$bestpart" ] || [ "$bestpart" = none ]; then log "Found no resizable partitions" elif longint_le "$(expr 3 \* 1024 \* 1024 \* 1024)" $bestfree; then log "Found resizable partition '$bestpart' ($bestpath) with $bestfree bytes free" db_subst partman-auto/text/resize_use_free PARTITION "$(humandev "$bestpath")" db_metaget partman-auto/text/resize_use_free description printf "%s\t%s" "$bestpart" "$RET" else log "Found resizable partition '$bestpart' ($bestpath), but not offering because only $bestfree bytes free" fi