Fix 1979: mib-bytes writes the bytes as a whole number for every size
mesh/delivery merged: source.main moved to novox/mesh-host@f8acfaeed79d
mesh/delivery-group group feature/1979-zfs-owns-zfs merged: every member is merged
mesh/check being carried to 96a869063977 on f8acfaeed79d | from 0193949efe9f, mesh-catalog 117f933dacf0, mesh-delivery 7221a1e5cd7f, mesh-sdk e42b9491…

A size of a million MiB or more reached the file in exponent form and was refused.

Builds: design 42 zfs-owns-zfs §3, A-24
This commit is contained in:
2026-11-13 01:32:36 +01:00
parent 7868c9f365
commit 96a8690639
2 changed files with 23 additions and 1 deletions
+15 -1
View File
@@ -3,6 +3,7 @@ package resolution
import (
"encoding/json"
"fmt"
"math"
"regexp"
"slices"
"strconv"
@@ -45,7 +46,7 @@ func configLinesInto(content string, layers []mcat.Layer, module string) (string
return token
}
if mib {
n, err := strconv.ParseUint(text, 10, 64)
n, err := mibWhole(text)
if err != nil || n > 1<<44 {
refused = fmt.Errorf("%s: the config value %q holds %q, and mib-bytes writes a whole number of MiB "+
"in bytes (design 42 §3)", module, key, text)
@@ -92,6 +93,19 @@ func configJSONInto(content string, layers []mcat.Layer, declared []string) (str
return configJSONRef.ReplaceAllLiteralString(content, object), nil
}
// mibWhole is a size in MiB as a whole number: digits, or a whole number a program wrote in exponent form (`1e+06`),
// which is how a float of a million or more prints (design 42 §3).
func mibWhole(text string) (uint64, error) {
if n, err := strconv.ParseUint(text, 10, 64); err == nil {
return n, nil
}
f, err := strconv.ParseFloat(text, 64)
if err != nil || f < 0 || f != math.Trunc(f) || f > 1<<44 {
return 0, fmt.Errorf("not a whole number of MiB")
}
return uint64(f), nil
}
// declaredConfig is the keys a module's manifest declares under `config`.
func declaredConfig(m mcat.Manifest) []string {
keys := make([]string, 0, len(m.Settings))
@@ -54,6 +54,14 @@ func TestAConfigValueReachesAResourceAndDecidesWhetherItIsDeclared(t *testing.T)
[]string{"${setting:domain}", "settings set mail", "set today: other"}},
{"config-lines: a list of two writes two lines in order", values(map[string]any{"k": []any{"a", "b"}}),
filled("h\n${config-lines:k:options zfs x=}\nt\n"), "h\noptions zfs x=a\noptions zfs x=b\nt\n", nil},
{"config-lines: mib-bytes writes a million MiB as a whole number", values(map[string]any{"k": float64(1000000)}),
filled("${config-lines:k:zfs_arc_max=:mib-bytes}\n"), "zfs_arc_max=1048576000000\n", nil},
{"config-lines: mib-bytes writes a million MiB given as text as a whole number", values(map[string]any{"k": "1000000"}),
filled("${config-lines:k:zfs_arc_max=:mib-bytes}\n"), "zfs_arc_max=1048576000000\n", nil},
{"config-lines: mib-bytes writes a size printed in exponent form as a whole number", values(map[string]any{"k": "1e+06"}),
filled("${config-lines:k:zfs_arc_max=:mib-bytes}\n"), "zfs_arc_max=1048576000000\n", nil},
{"config-lines: mib-bytes refuses a fraction", values(map[string]any{"k": "1.5"}),
filled("${config-lines:k:zfs_arc_max=:mib-bytes}\n"), "${config-lines:k:zfs_arc_max=:mib-bytes}\n", []string{"mib-bytes"}},
{"config-lines: an empty list writes nothing", values(map[string]any{"k": []any{}}),
filled("h\n${config-lines:k:p=}\nt\n"), "h\nt\n", nil},
{"config-lines: an unset value writes nothing", nil, filled("h\n${config-lines:k:p=}\nt\n"), "h\nt\n", nil},