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
binary-units-tests.tar.gz
Description: application/gzip