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

Bug#913431: Debian Installer Bullseye RC 2 release



Le 26/03/2023 à 18:38, Emanuele Rocca a écrit :
Hi Vincent,

On 2023-03-24 11:03, Vincent Danjean wrote:
However, I did not rebuild all the installer packages to generate a
new installer and test it in real conditions.

I haven't had the time to test your patch yet, but there's a hack I'd
like to share to test things in d-i without rebuilding anything.

Thank you very much for the tip. I see later that you can also
just go to the second console and type the "wget ..." instruction
here (before (re)starting the partitioning).
  This allows me to fix my patch: ${str:start:end} is not available
in the installer context, nor is ${str// /} to remove space.
I used 'cut' and 'tr' to do the job.

  With this updated patch, I successfully created plain (GPT)
partition in MiB and GiB (plain and fractional) and also
LVM LV in GiB (plain and fractional) with the Debian Installer
Bookworm Alpha 2 release (amd64 and i386 netinst CD images)
  The only 'bug' (but it should be present before) is that
the first partition for whose I asked a size of 128MiB gets
a size of 127MiB, probably due to the fact that the start
of the partition has been aligned to the first MiB (ie 1024kiB)

  Moreover, the tests I provide now also pass within the
installer (run the 'tests' script with the "di" argument to
avoid the script to try to run 'bc'). Both outputs (in d-i and
in a 'normal' machine) have the same md5sum (on amd64 and i386)

  So, I think I've done all what I can.

  Regards,
    Vincent


diff --git a/lib/base.sh b/lib/base.sh
index d38e101e..08cfec55 100644
--- a/lib/base.sh
+++ b/lib/base.sh
@@ -313,9 +313,125 @@ longint2human () {
 	printf "%i%s%i %s\n" $int $deci $frac $suffix
 }
 
+substr() {
+	local s="$1"
+	local start="$2" # first is 0
+	local size="$3"
+
+	if [ -n "$3" ]; then
+		echo "$s" | cut -c $(($start + 1))-$(($start + $size))
+	else
+		echo "$s" | cut -c $(($start + 1))-
+	fi
+}
+
+longmult() {
+	local a="$1" # no size limit
+	local b="$2" # <= 2^30
+
+	local carry=0
+	local endres=""
+	local partres
+	local enda
+
+	while [ "${#a}" -gt 6 ]; do
+		enda="$(substr "$a" $((${#a} - 6)))"
+		a="${a%$enda}"
+		partres="$(expr "$enda" '*' "$b" + "$carry")"
+		if [ "${#partres}" -gt 6 ]; then
+			carry="$(substr "$partres" 0 $((${#partres} - 6)))"
+			endres="${partres#$carry}$endres"
+		else
+			partres="000000$partres"
+			carry=0
+			endres="$(substr "$partres" $((${#partres} - 6)))$endres"
+		fi
+	done
+	partres="$(expr "$a" '*' "$b" + "$carry")"
+	echo "$partres$endres"
+}
+
+longadd() {
+	local a="$1" # no size limit
+	local b="$2" # <= 2^60
+
+	local carry="$b"
+	local endres=""
+	local partres
+	local enda
+
+	while [ "${#a}" -gt 15 ]; do
+		enda="$(substr "$a" $((${#a} - 15)))"
+		a="${a%$enda}"
+		partres="$(expr "$enda" + "$carry")"
+		if [ "${#partres}" -gt 15 ]; then
+			carry="$(substr "$partres" 0 $((${#partres} - 15)))"
+			endres="${partres#$carry}$endres"
+		else
+			partres="000000000000000$partres"
+			echo "${a}$(substr "$partres" $((${#partres} - 15)))$endres"
+			return
+		fi
+	done
+	partres="$(expr "$a" + "$carry")"
+	echo "$partres$endres"
+}
+
+human2longint_binary_unit() {
+	local int="$1"
+	local frac="$2"
+	local powbase="$3" # 1 <= powbase <= 6
+	# must return "$int.$frac * 1024^$powbase"
+	# contraints :
+	# - no floating point operation
+	# - no computed values above 2^63-1
+	# - expr has no exponentiation
+	# - bash arithmetics consider that 0-leading numbers are octal
+
+	# max of useful decimals when converting: powbase*10
+	# next ones, when multipled by 1024^powbase, would be <1
+	# so no need to take into account to many decimals
+	frac="$(substr "$frac" 0 $((powbase * 10 )))"
+	local longint="${int}${frac}"
+	longint="$(substr "$longint" $(expr "$longint" : '0*' || true))" # remove leading 0
+	[ "$longint" ] || {
+		echo 0
+		return
+	}
+	while [ "$powbase" -gt 3 ]; do
+		longint="$(longmult "$longint" "$((1024**3))")"
+		powbase=$(( $powbase - 3 ))
+	done
+	longint="$(longmult "$longint" "$((1024**$powbase))")"
+
+	if [ -z "$frac" ]; then
+		# no fractional part, just return the result
+		echo "$longint"
+		return
+	fi
+	# non-null fractional part.
+	# longint must be divided by 10^length(frac)
+	local posfrac="$(( ${#longint} - ${#frac} ))"
+	if [ $posfrac -le 0 ]; then
+		echo 0
+		return
+	fi
+	local res="$(substr "$longint" 0 $posfrac)"
+	# roundup if the next decimal is >= 5
+	case "$(substr "$longint" $posfrac 1)" in
+	[5-9]*) # roundup
+		longadd "$res" 1
+		;;
+	*)
+		echo "$res"
+		;;
+	esac
+}
+
 human2longint () {
-	local human orighuman gotb suffix int frac longint
-	set -- $*; human="$1$2$3$4$5" # without the spaces
+	local human orighuman gotb suffix int frac
+	local binary powbase dfrac
+	human="$(echo "$*" | tr -d ' ')" # without the spaces
 	orighuman="$human"
 	human=${human%b} #remove last b
 	human=${human%B} #remove last B
@@ -323,9 +439,18 @@ human2longint () {
 	if [ "$human" != "$orighuman" ]; then
 		gotb=1
 	fi
+	binary=${human#${human%?}} # the last symbol of $human
+	case $binary in
+	i)
+		human=${human%$binary}
+		;;
+	*)
+		binary=''
+		;;
+	esac
 	suffix=${human#${human%?}} # the last symbol of $human
 	case $suffix in
-	k|K|m|M|g|G|t|T)
+	k|K|m|M|g|G|t|T|p|P|e|E)
 		human=${human%$suffix}
 		;;
 	*)
@@ -337,49 +462,61 @@ human2longint () {
 		;;
 	esac
 	int="${human%[.,]*}"
-	[ "$int" ] || int=0
 	frac=${human#$int}
-	frac="${frac#[.,]}0000" # to be sure there are at least 4 digits
-	frac=${frac%${frac#????}} # only the first 4 digits of $frac
-	longint=$(expr "$int" \* 10000 + "$frac")
+	int="$(substr "$int" $(expr "$int" : '0*' || true))" # remove leading 0
+	[ "$int" ] || int=0
+	frac="${frac#[.,]}"
+	# to be sure there are at least 18 digits, the maximum possible precision for decimal units
+	dfrac="${frac}0000000000000000000"
 	case $suffix in
 	b|B)
-		longint=${longint%????}
-		[ "$longint" ] || longint=0
+		dfrac=
+		binary=''
 		;;
 	k|K)
-		longint=${longint%?}
+		powbase=1
+		dfrac=$(substr "$dfrac" 0 3) # only the first 3 digits of $dfrac
 		;;
-	m|M)
-		longint=${longint}00
+	m|M|'') # without units, suppose MB
+		powbase=2
+		dfrac=$(substr "$dfrac" 0 6)
 		;;
 	g|G)
-		longint=${longint}00000
+		powbase=3
+		dfrac=$(substr "$dfrac" 0 9)
 		;;
 	t|T)
-		longint=${longint}00000000
+		powbase=4
+		dfrac=$(substr "$dfrac" 0 12)
+		;;
+	p|P)
+		powbase=5
+		dfrac=$(substr "$dfrac" 0 15)
 		;;
-	*) # no suffix:
-		# bytes
-		#longint=${longint%????}
-		#[ "$longint" ] || longint=0
-		# megabytes
-		longint=${longint}00
+	e|E)
+		powbase=6
+		dfrac=$(substr "$dfrac" 0 18)
+		;;
+	esac
+	case "$binary" in
+	'')
+		echo "${int}${dfrac}"
 		;;
+	i)
+		human2longint_binary_unit "$int" "$frac" "$powbase"
 	esac
-	echo $longint
 }
 
 valid_human () {
 	local IFS patterns
 	patterns='[0-9][0-9]* *$
 [0-9][0-9]* *[bB] *$
-[0-9][0-9]* *[kKmMgGtT] *$
-[0-9][0-9]* *[kKmMgGtT][bB] *$
+[0-9][0-9]* *[kKmMgGtTpPeE] *$
+[0-9][0-9]* *[kKmMgGtTpPeE]i\?[bB] *$
 [0-9]*[.,][0-9]* *$
 [0-9]*[.,][0-9]* *[bB] *$
-[0-9]*[.,][0-9]* *[kKmMgGtT] *$
-[0-9]*[.,][0-9]* *[kKmMgGtT][bB] *$'
+[0-9]*[.,][0-9]* *[kKmMgGtTpPeE] *$
+[0-9]*[.,][0-9]* *[kKmMgGtTpPeE]i\?[bB] *$'
 	IFS="$NL"
 	for regex in $patterns; do
 		if expr "$1" : "$regex" >/dev/null; then return 0; fi

Attachment: binary-units-tests.tar.gz
Description: application/gzip


Reply to: