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