aboutsummaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rw-r--r--contrib/kyua/doc/kyuafile.5.in10
-rw-r--r--contrib/kyua/drivers/report_junit_test.cpp3
-rw-r--r--contrib/kyua/engine/atf_list.cpp2
-rw-r--r--contrib/kyua/engine/requirements.cpp57
-rw-r--r--contrib/kyua/engine/requirements.hpp26
-rw-r--r--contrib/kyua/integration/cmd_report_junit_test.sh4
-rw-r--r--contrib/kyua/integration/cmd_report_test.sh1
-rw-r--r--contrib/kyua/model/metadata.cpp16
-rw-r--r--contrib/kyua/model/metadata.hpp4
-rw-r--r--contrib/kyua/model/metadata_test.cpp6
-rw-r--r--contrib/kyua/model/test_case_test.cpp2
-rw-r--r--contrib/kyua/model/test_program_test.cpp8
-rw-r--r--contrib/kyua/os/freebsd/main.cpp11
-rw-r--r--contrib/kyua/os/freebsd/reqs_checker_kmods.cpp50
-rw-r--r--contrib/kyua/os/freebsd/reqs_checker_kmods.hpp54
-rw-r--r--contrib/one-true-awk/FIXES8
-rw-r--r--contrib/one-true-awk/main.c2
-rw-r--r--contrib/one-true-awk/run.c4
18 files changed, 213 insertions, 55 deletions
diff --git a/contrib/kyua/doc/kyuafile.5.in b/contrib/kyua/doc/kyuafile.5.in
index ae1e4fe40e32..43f00816d407 100644
--- a/contrib/kyua/doc/kyuafile.5.in
+++ b/contrib/kyua/doc/kyuafile.5.in
@@ -290,6 +290,16 @@ it can run.
.Pp
ATF:
.Va require.files
+.It Va required_kmods
+Whitespace-separated list of kernel module names that the test requires to
+be loaded before it can run.
+This requirement checking is platform-dependent.
+It is ignored for a non-supported platform.
+Supported platforms:
+.Fx .
+.Pp
+ATF:
+.Va require.kmods
.It Va required_memory
Amount of physical memory that the test needs to run successfully.
.Pp
diff --git a/contrib/kyua/drivers/report_junit_test.cpp b/contrib/kyua/drivers/report_junit_test.cpp
index 0f009c6befd3..1c0929c0fef2 100644
--- a/contrib/kyua/drivers/report_junit_test.cpp
+++ b/contrib/kyua/drivers/report_junit_test.cpp
@@ -70,6 +70,7 @@ static const char* const default_metadata =
"required_configs is empty\n"
"required_disk_space = 0\n"
"required_files is empty\n"
+ "required_kmods is empty\n"
"required_memory = 0\n"
"required_programs is empty\n"
"required_user is empty\n"
@@ -89,6 +90,7 @@ static const char* const overriden_metadata =
"required_configs is empty\n"
"required_disk_space = 0\n"
"required_files is empty\n"
+ "required_kmods is empty\n"
"required_memory = 0\n"
"required_programs is empty\n"
"required_user is empty\n"
@@ -228,6 +230,7 @@ ATF_TEST_CASE_BODY(junit_metadata__overrides)
+ "required_configs = config1\n"
+ "required_disk_space = 456\n"
+ "required_files = file1\n"
+ + "required_kmods is empty\n"
+ "required_memory = 123\n"
+ "required_programs = prog1\n"
+ "required_user = root\n"
diff --git a/contrib/kyua/engine/atf_list.cpp b/contrib/kyua/engine/atf_list.cpp
index e0c4170605d1..5c74a80be913 100644
--- a/contrib/kyua/engine/atf_list.cpp
+++ b/contrib/kyua/engine/atf_list.cpp
@@ -133,10 +133,8 @@ engine::parse_atf_metadata(const model::properties_map& props)
mdbuilder.set_string("required_disk_space", value);
} else if (name == "require.files") {
mdbuilder.set_string("required_files", value);
-#ifdef __FreeBSD__
} else if (name == "require.kmods") {
mdbuilder.set_string("required_kmods", value);
-#endif
} else if (name == "require.machine") {
mdbuilder.set_string("allowed_platforms", value);
} else if (name == "require.memory") {
diff --git a/contrib/kyua/engine/requirements.cpp b/contrib/kyua/engine/requirements.cpp
index dff43e531a57..d5838b83f33a 100644
--- a/contrib/kyua/engine/requirements.cpp
+++ b/contrib/kyua/engine/requirements.cpp
@@ -41,10 +41,6 @@
#include "utils/sanity.hpp"
#include "utils/units.hpp"
-#ifdef __FreeBSD__
-#include <libutil.h>
-#endif
-
namespace config = utils::config;
namespace fs = utils::fs;
namespace passwd = utils::passwd;
@@ -224,26 +220,6 @@ check_required_programs(const model::paths_set& required_programs)
}
-#ifdef __FreeBSD__
-/// Checks if all required kmods are loaded.
-///
-/// \param required_programs Set of kmods.
-///
-/// \return Empty if the required kmods are all loaded or an error
-/// message otherwise.
-static std::string
-check_required_kmods(const model::strings_set& required_kmods)
-{
- for (model::strings_set::const_iterator iter = required_kmods.begin();
- iter != required_kmods.end(); iter++) {
- if (!kld_isloaded((*iter).c_str()))
- return F("Required kmod '%s' not loaded") % *iter;
- }
- return "";
-}
-#endif
-
-
/// Checks if the current system has the specified amount of memory.
///
/// \param required_memory Amount of required physical memory, or zero if not
@@ -289,9 +265,29 @@ check_required_disk_space(const units::bytes& required_disk_space,
}
+/// List of registered extra requirement checkers.
+///
+/// Use register_reqs_checker() to add an entry to this global list.
+static std::vector< std::shared_ptr< engine::reqs_checker > > _reqs_checkers;
+
+
} // anonymous namespace
+const std::vector< std::shared_ptr< engine::reqs_checker > >
+engine::reqs_checkers()
+{
+ return _reqs_checkers;
+}
+
+void
+engine::register_reqs_checker(
+ const std::shared_ptr< engine::reqs_checker > checker)
+{
+ _reqs_checkers.push_back(checker);
+}
+
+
/// Checks if all the requirements specified by the test case are met.
///
/// \param md The test metadata.
@@ -336,12 +332,6 @@ engine::check_reqs(const model::metadata& md, const config::tree& cfg,
if (!reason.empty())
return reason;
-#ifdef __FreeBSD__
- reason = check_required_kmods(md.required_kmods());
- if (!reason.empty())
- return reason;
-#endif
-
reason = check_required_memory(md.required_memory());
if (!reason.empty())
return reason;
@@ -351,6 +341,13 @@ engine::check_reqs(const model::metadata& md, const config::tree& cfg,
if (!reason.empty())
return reason;
+ // Iterate over extra checkers registered.
+ for (auto& checker : engine::reqs_checkers()) {
+ reason = checker->exec(md, cfg, test_suite, work_directory);
+ if (!reason.empty())
+ return reason;
+ }
+
INV(reason.empty());
return reason;
}
diff --git a/contrib/kyua/engine/requirements.hpp b/contrib/kyua/engine/requirements.hpp
index a36a938b3034..92e80c5122aa 100644
--- a/contrib/kyua/engine/requirements.hpp
+++ b/contrib/kyua/engine/requirements.hpp
@@ -44,6 +44,32 @@ namespace engine {
std::string check_reqs(const model::metadata&, const utils::config::tree&,
const std::string&, const utils::fs::path&);
+/// Abstract interface of a requirement checker.
+class reqs_checker {
+public:
+ /// Constructor.
+ reqs_checker() {}
+
+ /// Destructor.
+ virtual ~reqs_checker() {}
+
+ /// Run the checker.
+ virtual std::string exec(const model::metadata&,
+ const utils::config::tree&,
+ const std::string&,
+ const utils::fs::path&) const = 0;
+};
+
+/// Register an extra requirement checker.
+///
+/// \param checker A requirement checker.
+void register_reqs_checker(const std::shared_ptr< reqs_checker > checker);
+
+/// Returns the list of registered extra requirement checkers.
+///
+/// \return A vector of pointers to extra requirement checkers.
+const std::vector< std::shared_ptr< reqs_checker > > reqs_checkers();
+
} // namespace engine
diff --git a/contrib/kyua/integration/cmd_report_junit_test.sh b/contrib/kyua/integration/cmd_report_junit_test.sh
index d86228acf7e5..49b8c5790167 100644
--- a/contrib/kyua/integration/cmd_report_junit_test.sh
+++ b/contrib/kyua/integration/cmd_report_junit_test.sh
@@ -104,6 +104,7 @@ is_exclusive = false
required_configs is empty
required_disk_space = 0
required_files is empty
+required_kmods is empty
required_memory = 0
required_programs is empty
required_user is empty
@@ -144,6 +145,7 @@ is_exclusive = false
required_configs is empty
required_disk_space = 0
required_files is empty
+required_kmods is empty
required_memory = 0
required_programs is empty
required_user is empty
@@ -222,6 +224,7 @@ is_exclusive = false
required_configs is empty
required_disk_space = 0
required_files is empty
+required_kmods is empty
required_memory = 0
required_programs is empty
required_user is empty
@@ -262,6 +265,7 @@ is_exclusive = false
required_configs is empty
required_disk_space = 0
required_files is empty
+required_kmods is empty
required_memory = 0
required_programs is empty
required_user is empty
diff --git a/contrib/kyua/integration/cmd_report_test.sh b/contrib/kyua/integration/cmd_report_test.sh
index 8b2b97f9cb4a..1fc1932d3c47 100644
--- a/contrib/kyua/integration/cmd_report_test.sh
+++ b/contrib/kyua/integration/cmd_report_test.sh
@@ -258,6 +258,7 @@ Metadata:
required_configs is empty
required_disk_space = 0
required_files is empty
+ required_kmods is empty
required_memory = 0
required_programs is empty
required_user is empty
diff --git a/contrib/kyua/model/metadata.cpp b/contrib/kyua/model/metadata.cpp
index a5a9a1315964..afb31435a238 100644
--- a/contrib/kyua/model/metadata.cpp
+++ b/contrib/kyua/model/metadata.cpp
@@ -256,9 +256,7 @@ init_tree(config::tree& tree)
tree.define< bytes_node >("required_disk_space");
tree.define< paths_set_node >("required_files");
tree.define< bytes_node >("required_memory");
-#ifdef __FreeBSD__
tree.define< config::strings_set_node >("required_kmods");
-#endif
tree.define< paths_set_node >("required_programs");
tree.define< user_node >("required_user");
tree.define< delta_node >("timeout");
@@ -285,9 +283,7 @@ set_defaults(config::tree& tree)
tree.set< bytes_node >("required_disk_space", units::bytes(0));
tree.set< paths_set_node >("required_files", model::paths_set());
tree.set< bytes_node >("required_memory", units::bytes(0));
-#ifdef __FreeBSD__
tree.set< config::strings_set_node >("required_kmods", model::strings_set());
-#endif
tree.set< paths_set_node >("required_programs", model::paths_set());
tree.set< user_node >("required_user", "");
// TODO(jmmv): We shouldn't be setting a default timeout like this. See
@@ -603,20 +599,20 @@ model::metadata::required_memory(void) const
}
-#ifdef __FreeBSD__
-/// Returns the list of kmods needed by the test.
+/// Returns the list of kernel modules needed by the test.
///
-/// \return Set of strings.
+/// \return Set of kernel module names.
const model::strings_set&
model::metadata::required_kmods(void) const
{
if (_pimpl->props.is_set("required_kmods")) {
- return _pimpl->props.lookup< config::strings_set_node >("required_kmods");
+ return _pimpl->props.lookup< config::strings_set_node >(
+ "required_kmods");
} else {
- return get_defaults().lookup< config::strings_set_node >("required_kmods");
+ return get_defaults().lookup< config::strings_set_node >(
+ "required_kmods");
}
}
-#endif
/// Returns the list of programs needed by the test.
diff --git a/contrib/kyua/model/metadata.hpp b/contrib/kyua/model/metadata.hpp
index 8af6c7c161af..eee7eaf0f7c4 100644
--- a/contrib/kyua/model/metadata.hpp
+++ b/contrib/kyua/model/metadata.hpp
@@ -76,9 +76,7 @@ public:
const utils::units::bytes& required_disk_space(void) const;
const paths_set& required_files(void) const;
const utils::units::bytes& required_memory(void) const;
-#ifdef __FreeBSD__
const strings_set& required_kmods(void) const;
-#endif
const paths_set& required_programs(void) const;
const std::string& required_user(void) const;
const utils::datetime::delta& timeout(void) const;
@@ -124,9 +122,7 @@ public:
metadata_builder& set_required_disk_space(const utils::units::bytes&);
metadata_builder& set_required_files(const paths_set&);
metadata_builder& set_required_memory(const utils::units::bytes&);
-#ifdef __FreeBSD__
metadata_builder& set_required_kmods(const strings_set&);
-#endif
metadata_builder& set_required_programs(const paths_set&);
metadata_builder& set_required_user(const std::string&);
metadata_builder& set_string(const std::string&, const std::string&);
diff --git a/contrib/kyua/model/metadata_test.cpp b/contrib/kyua/model/metadata_test.cpp
index b4c3dff5b029..bdb1d3655c33 100644
--- a/contrib/kyua/model/metadata_test.cpp
+++ b/contrib/kyua/model/metadata_test.cpp
@@ -57,6 +57,7 @@ ATF_TEST_CASE_BODY(defaults)
ATF_REQUIRE(md.required_configs().empty());
ATF_REQUIRE_EQ(units::bytes(0), md.required_disk_space());
ATF_REQUIRE(md.required_files().empty());
+ ATF_REQUIRE(md.required_kmods().empty());
ATF_REQUIRE_EQ(units::bytes(0), md.required_memory());
ATF_REQUIRE(md.required_programs().empty());
ATF_REQUIRE(md.required_user().empty());
@@ -322,6 +323,7 @@ ATF_TEST_CASE_BODY(to_properties)
props["required_configs"] = "";
props["required_disk_space"] = "0";
props["required_files"] = "bar foo";
+ props["required_kmods"] = "";
props["required_memory"] = "1.00K";
props["required_programs"] = "";
props["required_user"] = "";
@@ -412,7 +414,7 @@ ATF_TEST_CASE_BODY(output__defaults)
"has_cleanup='false', is_exclusive='false', "
"required_configs='', "
"required_disk_space='0', required_files='', "
- "required_memory='0', "
+ "required_kmods='', required_memory='0', "
"required_programs='', required_user='', timeout='300'}",
str.str());
}
@@ -435,7 +437,7 @@ ATF_TEST_CASE_BODY(output__some_values)
"has_cleanup='false', is_exclusive='true', "
"required_configs='', "
"required_disk_space='0', required_files='bar foo', "
- "required_memory='1.00K', "
+ "required_kmods='', required_memory='1.00K', "
"required_programs='', required_user='', timeout='300'}",
str.str());
}
diff --git a/contrib/kyua/model/test_case_test.cpp b/contrib/kyua/model/test_case_test.cpp
index 1e2597d1501e..29df7ee35863 100644
--- a/contrib/kyua/model/test_case_test.cpp
+++ b/contrib/kyua/model/test_case_test.cpp
@@ -204,7 +204,7 @@ ATF_TEST_CASE_BODY(test_case__output)
"has_cleanup='false', "
"is_exclusive='false', "
"required_configs='', required_disk_space='0', required_files='', "
- "required_memory='0', "
+ "required_kmods='', required_memory='0', "
"required_programs='', required_user='', timeout='300'}}",
str.str());
}
diff --git a/contrib/kyua/model/test_program_test.cpp b/contrib/kyua/model/test_program_test.cpp
index ddfbc430387c..f7a84d770fc0 100644
--- a/contrib/kyua/model/test_program_test.cpp
+++ b/contrib/kyua/model/test_program_test.cpp
@@ -547,7 +547,7 @@ check_output__no_test_cases(void)
"description='', execenv='', execenv_jail_params='', "
"has_cleanup='false', is_exclusive='false', "
"required_configs='', required_disk_space='0', required_files='', "
- "required_memory='0', "
+ "required_kmods='', required_memory='0', "
"required_programs='', required_user='', timeout='300'}, "
"test_cases=map()}",
str.str());
@@ -597,7 +597,7 @@ check_output__some_test_cases(void)
"description='', execenv='', execenv_jail_params='', "
"has_cleanup='false', is_exclusive='false', "
"required_configs='', required_disk_space='0', required_files='', "
- "required_memory='0', "
+ "required_kmods='', required_memory='0', "
"required_programs='', required_user='', timeout='300'}, "
"test_cases=map("
"another-name=test_case{name='another-name', "
@@ -605,14 +605,14 @@ check_output__some_test_cases(void)
"description='', execenv='', execenv_jail_params='', "
"has_cleanup='false', is_exclusive='false', "
"required_configs='', required_disk_space='0', required_files='', "
- "required_memory='0', "
+ "required_kmods='', required_memory='0', "
"required_programs='', required_user='', timeout='300'}}, "
"the-name=test_case{name='the-name', "
"metadata=metadata{allowed_architectures='a', allowed_platforms='foo', "
"custom.bar='baz', description='', execenv='', execenv_jail_params='', "
"has_cleanup='false', is_exclusive='false', "
"required_configs='', required_disk_space='0', required_files='', "
- "required_memory='0', "
+ "required_kmods='', required_memory='0', "
"required_programs='', required_user='', timeout='300'}})}",
str.str());
}
diff --git a/contrib/kyua/os/freebsd/main.cpp b/contrib/kyua/os/freebsd/main.cpp
index 13e5dcf0e023..700284b64b78 100644
--- a/contrib/kyua/os/freebsd/main.cpp
+++ b/contrib/kyua/os/freebsd/main.cpp
@@ -31,6 +31,9 @@
#include "engine/execenv/execenv.hpp"
#include "os/freebsd/execenv_jail_manager.hpp"
+#include "engine/requirements.hpp"
+#include "os/freebsd/reqs_checker_kmods.hpp"
+
namespace execenv = engine::execenv;
/// FreeBSD related features initialization.
@@ -50,5 +53,13 @@ freebsd::main(const int, const char* const* const)
std::shared_ptr< execenv::manager >(new freebsd::execenv_jail_manager())
);
+#ifdef __FreeBSD__
+ engine::register_reqs_checker(
+ std::shared_ptr< engine::reqs_checker >(
+ new freebsd::reqs_checker_kmods()
+ )
+ );
+#endif
+
return 0;
}
diff --git a/contrib/kyua/os/freebsd/reqs_checker_kmods.cpp b/contrib/kyua/os/freebsd/reqs_checker_kmods.cpp
new file mode 100644
index 000000000000..3ae3446a7815
--- /dev/null
+++ b/contrib/kyua/os/freebsd/reqs_checker_kmods.cpp
@@ -0,0 +1,50 @@
+// Copyright 2025 The Kyua Authors.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "os/freebsd/reqs_checker_kmods.hpp"
+
+#include "model/metadata.hpp"
+
+extern "C" {
+#include "libutil.h"
+}
+
+std::string
+freebsd::reqs_checker_kmods::exec(const model::metadata& md,
+ const utils::config::tree&,
+ const std::string&,
+ const utils::fs::path&) const
+{
+ std::string reason = "";
+ for (auto& kmod : md.required_kmods())
+ if (!::kld_isloaded((kmod).c_str()))
+ reason += " " + kmod;
+ if (!reason.empty())
+ reason = "Required kmods are not loaded:" + reason + ".";
+ return reason;
+}
diff --git a/contrib/kyua/os/freebsd/reqs_checker_kmods.hpp b/contrib/kyua/os/freebsd/reqs_checker_kmods.hpp
new file mode 100644
index 000000000000..8c7c69e35d07
--- /dev/null
+++ b/contrib/kyua/os/freebsd/reqs_checker_kmods.hpp
@@ -0,0 +1,54 @@
+// Copyright 2025 The Kyua Authors.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/// \file os/freebsd/reqs_checker_kmods.hpp
+/// FreeBSD kernel module requirement checker.
+
+#if !defined(FREEBSD_REQS_CHECKER_KMODS)
+#define FREEBSD_REQS_CHECKER_KMODS
+
+#include "engine/requirements.hpp"
+#include "model/metadata_fwd.hpp"
+#include "utils/config/tree_fwd.hpp"
+#include "utils/fs/path_fwd.hpp"
+
+namespace freebsd {
+
+
+class reqs_checker_kmods : public engine::reqs_checker {
+public:
+ std::string exec(const model::metadata&,
+ const utils::config::tree&,
+ const std::string&,
+ const utils::fs::path&) const;
+};
+
+
+} // namespace freebsd
+
+#endif // !defined(FREEBSD_REQS_CHECKER_KMODS)
diff --git a/contrib/one-true-awk/FIXES b/contrib/one-true-awk/FIXES
index b3bf38f0aa1c..b876b9ec5ec9 100644
--- a/contrib/one-true-awk/FIXES
+++ b/contrib/one-true-awk/FIXES
@@ -25,6 +25,14 @@ THIS SOFTWARE.
This file lists all bug fixes, changes, etc., made since the
second edition of the AWK book was published in September 2023.
+Aug 04, 2025
+ Fix incorrect divisor in rand() - it was returning
+ even random numbers only. Thanks to Ozan Yigit.
+
+ Fix a syntax issue with /= that caused constants to
+ turn into variables [eg. 42 /= 7]. Thanks to Arnold
+ Robbins.
+
Jan 14, 2025
Fix incorrect error line number issues. unput has
no business managing lineno. Thanks to Ozan Yigit.
diff --git a/contrib/one-true-awk/main.c b/contrib/one-true-awk/main.c
index 361c23e70861..b8053af34b05 100644
--- a/contrib/one-true-awk/main.c
+++ b/contrib/one-true-awk/main.c
@@ -22,7 +22,7 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
****************************************************************/
-const char *version = "version 20250116";
+const char *version = "version 20250804";
#define DEBUG
#include <stdio.h>
diff --git a/contrib/one-true-awk/run.c b/contrib/one-true-awk/run.c
index eaddfdecbdd3..9bc07a517372 100644
--- a/contrib/one-true-awk/run.c
+++ b/contrib/one-true-awk/run.c
@@ -1567,6 +1567,8 @@ Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */
xf *= yf;
break;
case DIVEQ:
+ if ((x->tval & CON) != 0)
+ FATAL("non-constant required for left side of /=");
if (yf == 0)
FATAL("division by zero in /=");
xf /= yf;
@@ -2188,7 +2190,7 @@ Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg lis
/* random() returns numbers in [0..2^31-1]
* in order to get a number in [0, 1), divide it by 2^31
*/
- u = (Awkfloat) random() / (0x7fffffffL + 0x1UL);
+ u = (Awkfloat) random() / RAND_MAX;
break;
case FSRAND:
if (isrec(x)) /* no argument provided */