Commit graph

2220 commits

Author SHA1 Message Date
Bob Badour
8fc610ffc8 Clean up license texts.
Test: m droid dist

Change-Id: Ib37f6a039098c2f934c8f040682703b519043fc5
2022-08-11 11:53:15 -07:00
Mike McTernan
7f68de32c6 ANDROID: fuzz: Rename libfdt_fuzzer.cpp to .c
Change cpp to c file ahead of further extensions to the fuzzing test
harness. This simplifies building afl-fuzz or with just C tools, but
could be made C++ again if needed in the future.

Test: build and ran libFuzzer test
Change-Id: Ibc7edc8834fa71d4bbabac826efccb49d8a1be38
Merged-In: I8873883ab5b91f36b707cd9d05856aa4c9c222bd
2022-08-10 16:28:40 +01:00
Pierre-Clément Tosi
354123a2d1 ANDROID: Merge upstream c2ccf8a77d (v1.6.1)
Bug: 238913758
Test: -
Signed-off-by: Pierre-Clément Tosi <ptosi@google.com>
Change-Id: I43c4e721d5778e5b214c70c6084026a4bb4933b8
2022-07-29 11:19:47 +01:00
David Gibson
c2ccf8a77d Add description of Signed-off-by lines
dtc and libfdt have been using Signed-off-by lines (as used in the Linux
kernel) for some time, like a lot of open source projects.  However
Uwe Kleine-König pointed out we never really stated what they mean in our
context.

Add information on what the S-o-b line means in CONTRIBUTING.md - this is
essentially a quote of the same information from the kernel documentation,
with some tweaks to make sense in the new context.

Suggested-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
2022-07-29 12:55:15 +10:00
David Gibson
90b9d9de42 Split out information for contributors to CONTRIBUTING.md
README.md covers both general information for people using and building
the software, and more specific information for people contributing to
either dtc or libfdt.  Split out the latter information into its own file
for easier reference.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-07-28 16:25:56 +10:00
David Gibson
0ee1d479b2 Remove Jon Loeliger from maintainers list
Jon hasn't been actively working on dtc maintenance for some years.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-07-28 16:16:08 +10:00
David Gibson
b33a73c62c Convert README to README.md
Let's move vaguely into the twenty-first century by converting our old
plain text README file to Markdown.  While we're updating the formatting,
make some small polish changes to the content.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-07-28 16:15:06 +10:00
Tero Tervala
7ad60734b1 Allow static building with meson
Added "static-build" option in the meson_options.txt.
Setting it to "true" allows static building.

Signed-off-by: Tero Tervala <tero.tervala@unikie.com>
Message-Id: <20220629163557.932298-1-tero.tervala@unikie.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-07-27 16:38:45 +10:00
Tero Tervala
fd9b8c96c7 Allow static building with make
Set STATIC_BUILD=1 environment variable to enable static building
when using makefiles.

Signed-off-by: Tero Tervala <tero.tervala@unikie.com>
Message-Id: <20220629163531.932281-1-tero.tervala@unikie.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-07-27 16:35:29 +10:00
Pierre-Clément Tosi
fda71da26e libfdt: Handle failed get_name() on BEGIN_NODE
Validate the return value of fdt_get_name() as an ill-formed DT, causing
it to fail, could result in fdt_check_full() dereferencing NULL.

fixes: a2def54799 ("libfdt: Check that the root-node name is empty")
Signed-off-by: Pierre-Clément Tosi <ptosi@google.com>
Message-Id: <20220714083848.958492-1-ptosi@google.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-07-26 21:46:18 +10:00
Tero Tervala
c7c7f17a83 Fix test script to run also on dash shell
/bin/sh points to dash instead of bash in some linux distros.
One test would fail if dash was used, this fix will allow all tests
to run properly on dash too.

dash built-in printf does not support "\xNN" -hex escape format.
"\NNN" -octal escape format is supported by both bash and dash printf.

Replaced "$(echo "$expect")" because this actually runs /bin/echo
instead of shell internal echo and in some cases causes "\NNN" escapes
to be printed as the actual characters they represent instead of the
escape sequence itself.

Cosmetic quotes added to make printout a bit clearer.

Signed-off-by: Tero Tervala <tero.tervala@unikie.com>
Message-Id: <20220704073722.1075849-1-tero.tervala@unikie.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-07-26 21:39:07 +10:00
Pierre-Clément Tosi
bb7fb360ba OWNERS: Add mikemcternan@
Make Mike an owner of DTC (libfdt) given his work on the fuzzer and the
dependency his team has on the library.

Move our names above the automatically generated comment to distinguish
between owners that were added manually and owners that weren't.

Test: -
Signed-off-by: Pierre-Clément Tosi <ptosi@google.com>
Change-Id: If41a7c9b6277da036ff4d47f2fb189e1c4621ef0
2022-07-26 12:05:37 +01:00
Mike McTernan
856cbfcf99 Add ptosi to owners.
Test: manual - checked email address.
Change-Id: Icb2994f0992ff61ee572c739e4dc513ef5c5681e
2022-07-25 09:20:25 +01:00
Mike McTernan
09bf0ed096 Fix 'make check' target so it builds.
Test: make check
Test: build android
Change-Id: I8e998651402f8243ee4d222a5a2518adeeb4ace7
2022-07-25 06:41:04 +01:00
Pierre-Clément Tosi
11f671ae84 fuzzing: Validate FDT size before walking it
As a user of libfdt, the fuzzer is expected to fully validate the
untrusted DT before reading from it so call fdt_check_full(), which also
validates the size of the DT (as described in its header) against the
received buffer size, to prevent OOBs.

Bug: 230794395
Test: SANITIZE_HOST=address m libfdt_fuzzer
Test: out/host/linux-x86/fuzz/x86_64/libfdt_fuzzer/libfdt_fuzzer
Signed-off-by: Pierre-Clément Tosi <ptosi@google.com>
Change-Id: Ic4f4e7355e4978022001ee34b21fc7219adf1d56
2022-07-11 12:32:44 +01:00
Tero Tervala
01f23ffe16 Add missing relref_merge test to meson test list
Will remove one "Strange test result" when running tests with
meson

Signed-off-by: Tero Tervala <tero.tervala@unikie.com>
Message-Id: <20220629163114.932175-1-tero.tervala@unikie.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-07-02 16:37:02 +10:00
Treehugger Robot
4bd86627f0 Merge "Update libfdt fuzzer owners." 2022-06-15 16:52:07 +00:00
Eugene Rodionov
cade769e4e Update libfdt fuzzer owners.
Add ptosi@google.com as libfdt fuzzer owner.

Change-Id: Ie759dcc06eb375906bb67a0cab063779f022abbc
2022-06-15 08:53:28 +01:00
Pierre-Clément Tosi
48f9fd6793 ANDROID: Merge upstream ed310803ea (v1.6.1) am: 9c26cc838f
Original change: https://android-review.googlesource.com/c/platform/external/dtc/+/2111064

Change-Id: Id38c4d7e214e727716e49cb8abf885b425887eed
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
2022-06-01 08:01:12 +00:00
Pierre-Clément Tosi
9c26cc838f ANDROID: Merge upstream ed310803ea (v1.6.1)
Upgrade to the latest master from

    git://git.kernel.org/pub/scm/utils/dtc/dtc.git.

at commit ed310803ea.

Bug: 221191119
Bug: 222320399
Bug: 230794395
Bug: 234413190
Change-Id: I6cc623e217641d7db3d4f2c4873cda472da08ef4
2022-05-31 09:16:03 +01:00
Luca Weiss
ed310803ea pylibfdt: add FdtRo.get_path()
Add a new Python method wrapping fdt_get_path() from the C API.

Also add a test for the new method.

Signed-off-by: Luca Weiss <luca@z3ntu.xyz>
Message-Id: <20220419194537.63170-1-luca@z3ntu.xyz>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-04-20 12:55:14 +10:00
Eugene Rodionov
1511571160 Create an initial version of libfdt fuzzer. am: 49a2e71ae0 am: 85189c3a6a
Original change: https://android-review.googlesource.com/c/platform/external/dtc/+/1987187

Change-Id: I2c357eccf0a0999cf4679a0f81df3a235ad6aa02
2022-02-23 19:45:58 +00:00
Eugene Rodionov
85189c3a6a Create an initial version of libfdt fuzzer. am: 49a2e71ae0
Original change: https://android-review.googlesource.com/c/platform/external/dtc/+/1987187

Change-Id: Ibc4f2ae2010ae295be48e179970a9fa9de3f4eaa
2022-02-23 19:20:03 +00:00
Eugene Rodionov
49a2e71ae0 Create an initial version of libfdt fuzzer.
Test: SANITIZE_HOST=address m libfdt_fuzzer
Test: out/host/linux-x86/fuzz/x86_64/libfdt_fuzzer/libfdt_fuzzer

Bug: 217650981
Change-Id: Ib1e26fe0b8e8d3f94fc1c5455853d57ccf348d1c
2022-02-17 01:14:59 +00:00
Rob Herring
c001fc01a4 pylibfdt: fix swig build in install
A 'pip install' is silently broken unless the tree is dirty and contains
pylibfdt/libfdt.py. The problem is a known issue[1] with SWIG and
setuptools where the 'build_py' stage needing module.py runs before
the 'build_ext' stage which generates it. The work-around is to override
'build_py' to run 'build_ext' first.

[1] https://stackoverflow.com/questions/50239473/building-a-module-with-setuptools-and-swig

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20220203180408.611645-2-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-02-04 18:52:36 +11:00
Ahmad Fatoum
26c54f840d tests: add test cases for label-relative path references
Newly added &{label/path} feature doesn't yet have any tests. Add some.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
2022-01-25 17:10:47 +11:00
Ahmad Fatoum
ec7986e682 dtc: introduce label relative path references
Reference via label allows extending nodes with compile-time checking of
whether the node being extended exists. This is useful to catch
renamed/removed nodes after an update of the device trees to be extended.

In absence of labels in the original device trees, new style path
references can be used:

  /* upstream device tree */
  / {
	leds: some-non-standard-led-controller-name {
		led-0 {
			default-state = "off";
		};
	};
  };

  /* downstream device tree */
  &{/some-non-standard-led-controller-name/led-0} {
	default-state = "on";
  };

This is a common theme within the barebox bootloader[0], which extends the
upstream (Linux) device trees in that manner. The downside is that,
especially for deep nodes, these references can get quite long and tend to
break often due to upstream rework (e.g. rename to adhere to bindings).

Often there is a label a level or two higher that could be used. This
patch allows combining both a label and a new style path reference to
get a compile-time-checked reference, which allows rewriting the
previous downstream device tree snippet to:

  &{leds/led-0} {
	default-state = "on";
  };

This won't be broken when /some-non-standard-led-controller-name is
renamed or moved while keeping the label. And if led-0 is renamed, we
will get the expected compile-time error.

Overlay support is skipped for now as they require special support: The
label and relative path parts need to be resolved at overlay apply-time,
not at compile-time.

[0]: https://www.barebox.org/doc/latest/devicetree/index.html

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
2022-01-25 17:10:47 +11:00
Ahmad Fatoum
651410e54c util: introduce xstrndup helper
We already have xstrdup, add xstrndup as well to make it
straight-forward to clone part of a string.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
2022-01-25 17:10:47 +11:00
Hridya Valsaraju
b1faaed329 Remove hridya@ from OWNERS file am: 3c9bd3b578 am: bf1cc57752 am: 684718de6a
Original change: https://android-review.googlesource.com/c/platform/external/dtc/+/1940085

Change-Id: I1d7a9d4e1ce6d2d0cc6c5e48b1b4841313e359b0
2022-01-07 08:37:42 +00:00
Hridya Valsaraju
684718de6a Remove hridya@ from OWNERS file am: 3c9bd3b578 am: bf1cc57752
Original change: https://android-review.googlesource.com/c/platform/external/dtc/+/1940085

Change-Id: I9203dabb843f5e48a28e8c4cc2992385bd267ece
2022-01-07 08:24:30 +00:00
Hridya Valsaraju
bf1cc57752 Remove hridya@ from OWNERS file am: 3c9bd3b578
Original change: https://android-review.googlesource.com/c/platform/external/dtc/+/1940085

Change-Id: Icb74bb26b8bfaf5fce858a4b884f44cdd28898fb
2022-01-07 08:09:01 +00:00
Hridya Valsaraju
3c9bd3b578 Remove hridya@ from OWNERS file
Test: N/A
Bug: N/A
Change-Id: Icbcb60ef40259b0b8ef700bbe6c6fc7cca83236a
2022-01-06 16:50:50 -08:00
Marc-André Lureau
4048aed12b setup.py: fix out of tree build
Fixes: commit 1cc41b1c9 ("pylibfdt: Add packaging metadata")

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20220103073855.1468799-3-marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-01-04 10:48:59 +11:00
David Gibson
ff5afb96d0 Handle integer overflow in check_property_phandle_args()
If the corresponding '#xxx-cells' value is much too large, an integer
overflow can prevent the checks in check_property_phandle_args() from
correctly determining that the checked property is too short for the
given cells value.  This leads to an infinite loops.

This patch fixes the bug, and adds a testcase for it.  Further
information in https://github.com/dgibson/dtc/issues/64

Reported-by: Anciety <anciety@pku.edu.cn>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-12-29 17:04:18 +11:00
Simon Glass
ca72944343 README: Explain how to add a new API function
This is not obvious so add a little note about it.

Signed-off-by: Simon Glass <sjg@chromium.org>
Message-Id: <20211107224346.3181320-2-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-12-28 20:14:05 +11:00
LoveSy
c0c2e115f8 Fix a UB when fdt_get_string return null
When fdt_get_string return null, `namep` is not correctly reset.
From the document of `fdt_getprop_by_offset`, the parameter `namep` will
be always overwritten (that is, it will be overwritten without exception
of error occurance).

As for the caller (like
e097c097fe/native/jni/magiskboot/dtb.cpp (L42)),
the code may be like:
```cpp
size_t size;
const char *name;
auto *value = fdt_getprop_by_offset(fdt, prop, &name, &size);
```
and if `value == nullptr`, `size` is also be overwritten correctly but
`name` is not, which is quite inconsistent.

This commit makes sure `name` and `size` behavior consistently (reset to
reasonable value) when error occurs.

Signed-off-by: LoveSy <shana@zju.edu.cn>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-12-28 20:11:11 +11:00
Ahmad Fatoum
cd5f69cbc0 tests: setprop_inplace: use xstrdup instead of unchecked strdup
This is the only strdup instance we have, all others are xstrdup. As
strdup is _POSIX_C_SOURCE >= v200809L, which we don't require and we
don't check strdup error return here, switch to xstrdup instead. This
aligns the test with others that call xfuncs, mainly xmalloc().

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-12-28 20:10:57 +11:00
Luca Weiss
a04f690250 pylibfdt: add Property.as_*int*_array()
Add new methods to handle decoding of int32, uint32, int64 and uint64
arrays.

Also add tests for the new methods.

Signed-off-by: Luca Weiss <luca@z3ntu.xyz>
Message-Id: <20211225132558.167123-3-luca@z3ntu.xyz>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-12-28 15:30:33 +11:00
Luca Weiss
83102717d7 pylibfdt: add Property.as_stringlist()
Add a new method for decoding a string list property, useful for e.g.
the "reg-names" property.

Also add a test for the new method.

Signed-off-by: Luca Weiss <luca@z3ntu.xyz>
Message-Id: <20211225132558.167123-2-luca@z3ntu.xyz>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-12-28 15:29:31 +11:00
Luca Weiss
d152126bb0 Fix Python crash on getprop deallocation
Fatal Python error: none_dealloc: deallocating None
Python runtime state: finalizing (tstate=0x000055c9bac70920)

Current thread 0x00007fbe34e47740 (most recent call first):
  <no Python frame>
Aborted (core dumped)

This is caused by a missing Py_INCREF on the returned Py_None, as
demonstrated e.g. in https://github.com/mythosil/swig-python-incref or
described at https://edcjones.tripod.com/refcount.html ("Remember to
INCREF Py_None!")

A PoC for triggering this crash is uploaded to
https://github.com/z3ntu/pylibfdt-crash .
With this patch applied to pylibfdt the crash does not happen.

Signed-off-by: Luca Weiss <luca@z3ntu.xyz>
Message-Id: <20211224102811.70695-1-luca@z3ntu.xyz>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-12-26 15:44:32 +11:00
Rafał Miłecki
17739b7ef5 Support 'r' format for printing raw bytes with fdtget
FT is sometimes used for storing raw data. That is quite common for
U-Boot FIT images.

Extracting such data is not trivial currently. Using type 's' (string)
will replace every 0x00 (NUL) with 0x20 (space). Using type 'x' will
print bytes but in xxd incompatible format.

This commit adds support for 'r' (raw) format. Example usage:
fdtget -t r firmware.itb /images/foo data > image.raw

Support for encoding isn't added as there isn't any clean way of passing
binary data as command line argument.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Message-Id: <20211209061420.29466-1-zajec5@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-12-09 17:48:58 +11:00
Vikram Garhwal
45f3d1a095 libfdt: overlay: make overlay_get_target() public
This is done to get the target path for the overlay nodes which is very useful
in many cases. For example, Xen hypervisor needs it when applying overlays
because Xen needs to do further processing of the overlay nodes, e.g. mapping of
resources(IRQs and IOMMUs) to other VMs, creation of SMMU pagetables, etc.

Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
Message-Id: <1637204036-382159-2-git-send-email-fnu.vikram@xilinx.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-11-18 16:25:10 +11:00
Elvira Khabirova
c19a4bafa5 libfdt: fix an incorrect integer promotion
UINT32_MAX is an integer of type unsigned int. UINT32_MAX + 1 overflows
unless explicitly computed as unsigned long long. This led to some
invalid addresses being treated as valid.

Cast UINT32_MAX to uint64_t explicitly.

Signed-off-by: Elvira Khabirova <e.khabirova@omp.ru>
2021-11-17 12:22:53 +11:00
Rob Herring
1cc41b1c96 pylibfdt: Add packaging metadata
PyPI expects to have various package metadata including long
description, license, and classifiers. Add them.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20211112041633.741598-3-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-11-12 15:58:23 +11:00
Rob Herring
db72398cd4 README: Update pylibfdt install instructions
Now that pip is supported for installs, update the install instructions to
use it. Using pip over setup.py is generally recommended and simpler.

Also, drop 'SETUP_PREFIX' as it doesn't exist anywhere.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20211112041633.741598-2-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-11-12 15:58:23 +11:00
Ross Burton
383e148b70 pylibfdt: fix with Python 3.10
Since Python 2.5 the argument parsing functions when parsing expressions
such as s# (string plus length) expect the length to be an int or a
ssize_t, depending on whether PY_SSIZE_T_CLEAN is defined or not.

Python 3.8 deprecated the use of int, and with Python 3.10 this symbol
must be defined and ssize_t used[1].

Define the magic symbol when building the extension, and cast the ints
from the libfdt API to ssize_t as appropriate.

[1] https://docs.python.org/3.10/whatsnew/3.10.html#id2

Signed-off-by: Ross Burton <ross.burton@arm.com>
Message-Id: <20211111160536.2516573-1-ross.burton@arm.com>
[dwg: Adjust for new location of setup.py]
Tested-by: Rob Herring <robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-11-12 12:45:46 +11:00
Rob Herring
23b56cb7e1 pylibfdt: Move setup.py to the top level
Using 'pip' and several setup.py sub-commands currently don't work with
pylibfdt. The primary reason is Python packaging has opinions on the
directory structure of repositories and one of those appears to be the
inability to reference source files outside of setup.py's subtree. This
means a sdist cannot be created with all necessary source components
(i.e. libfdt headers). Moving setup.py to the top-level solves these
problems.

With this change. the following commands now work:

Creating packages for pypi.org:
./setup.py sdist bdist_wheel

Using pip for installs:
pip install .
pip install git+http://github.com/robherring/dtc.git@pypi-v2

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20211111011135.2386773-5-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-11-11 14:34:51 +11:00
Rob Herring
69a760747d pylibfdt: Split setup.py author name and email
The 'author' field in setup.py is supposed to be just the name. The
email address goes in 'author_email' field.

Cc: Simon Glass <sjg@chromium.org>
Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20211111011135.2386773-4-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-11-11 14:34:51 +11:00
Rob Herring
0b106a77db pylibfdt: Use setuptools_scm for the version
The DTC version in version_gen.h causes a warning with setuptools:

setuptools/dist.py:501: UserWarning: The version specified ('1.6.1-g5454474d') \
is an invalid version, this may not work as expected with newer versions of \
setuptools, pip, and PyPI. Please see PEP 440 for more details.

It also creates an unnecessary dependency on the rest of the build
system(s). Switch to use setuptools_scm instead to get the version for
pylibfdt.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20211111011135.2386773-3-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-11-11 14:30:33 +11:00
Rob Herring
c691776ddb pylibfdt: Use setuptools instead of distutils
The use of setuptools is favored over distutils. setuptools is needed to
support building Python 'wheels' and for pip support.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20211111011135.2386773-2-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-11-11 14:29:12 +11:00