Commit Graph
16626 Commits
Author SHA1 Message Date
Justin ! 0d14c2b67a libmain: always print all information when calling nix --version
This commit remove a check for the log level in the `printVersion()`
function that was making `nix --version` behaving weirdly and
inconsistently compared to other `nix-*` commands.

The root cause is the following code in `lix/nix/main.cc` that change
the log level at runtime if nix is call interactively:

```cpp
if (isatty(STDERR_FILENO)) {
  verbosity = lvlNotice;
} else {
  verbosity = lvlInfo;
}
```

This should be removed, but since it has more implication it's gonna be
done in another CL.

Fix: https://git.lix.systems/lix-project/lix/issues/620
Change-Id: Id2c83c51d7ef799ee2f9b8dbdd2bfaeaf2df6188
2025-01-16 22:56:42 -05:00
Jade Lovelace 9760c00591 clang-tidy: Obliterate FixIncludes check
We have obliterated the support across the build system for these
include paths anywhere, so the codemod is now redundant and can go.

Change-Id: I54082f39752c6aac6429e1c24026211adae8221a
2025-01-16 00:12:57 -08:00
Jade Lovelace bf3ebde25f pkg-config: remove legacy include paths!
This is a breaking change for non-migrated external clients. External
users always need to use <lix/libcmd/foo.hh> type include paths now.

This is as was always planned with the include rearrangement.

Change-Id: I269be91ff9f9cc94d5d3043cf3e0bdf8db1d8edb
2025-01-16 00:12:57 -08:00
eldritch horrorsandGerrit Code Review 423d8b03c8 Merge "libutil: thread-pool: ensure threads finished on error" into main 2025-01-15 22:33:30 +00:00
Jade Lovelace acbb3cff2d Merge remote-tracking branch 'pennae/path-access' into HEAD
This fixes a bug where flakes do not actually do purity path checks
correctly.

Tested-By: Jade Lovelace <lix@jade.fyi>
Change-Id: If7d131a8e73a5874fb15cfaa0dea3b8811ba35d2
2025-01-13 17:19:54 -08:00
Maximilian BoschandGerrit Code Review 38dd196b03 Merge "libstore: fix "illegal reference specifier 'man'"-error in postgresql_14" into main 2025-01-12 11:12:12 +00:00
Jade Lovelaceandeldritch horrors d46adb45eb tests: validate that flakes do path traversal checking
Apparently we had zero test coverage of this, let's fix that.

Change-Id: I00c906daf5acfc01913562036ca88abbf63dd3d9
2025-01-11 20:42:30 +01:00
eldritch horrors 0dbfa7b26e libexpr: forbid allowed -> disallowed -> allowed links
this is more of a theoretical problem, but it does allow changing the
behavior of a flake depending on mutable machine state. it's unlikely
that this could be used to reliably do anything bad, but it does lead
to even more non-determinstic evaluation of (notionally) pure flakes.

Change-Id: I5bac7ed045046da08a36c764ab887bc9c7551542
2025-01-11 20:42:30 +01:00
Dominique Martinet 4737d8b65e libutil: thread-pool: ensure threads finished on error
This fixes segfaults with nix copy when there was an error processing
addMultipleToStore.

Running with ASAN/TSAN pointed at an use-after-free with threads from
the pool accessing the graph declared in processGraph after the function
was exiting and destructing the variables.

It turns out that if there is an error before pool.process() is called,
for example while we are still enqueueing tasks, then pool.process()
isn't called and threads are still left to run.

By creating the pool last we ensure that it is stopped first before
running other destructors even if an exception happens early.

fixes #618

Change-Id: I42a355f632aa0354df94c5d5d8cbe7ab5196c9a6
2025-01-12 04:14:28 +09:00
eldritch horrorsandJade Lovelace c948b350fb libutil: add CheckedSourcePath for accessing things
SourcePath only manipulates path names now. all accesses must go through
a checked path going forward to ensure we don't escape restriction lists
of pure and restricted evaluation. if a directory path is checked it can
safely be assumed that the directory itself is allowed, and its contents
will likewise be safe to access. it is tempting to assumed that contents
will also be fine, but that's only true if the content is not a symlink.

Change-Id: Icec3098d53fe9dce50997954ba958fe4f304d59b
2025-01-10 15:20:27 -08:00
eldritch horrorsandJade Lovelace 8db8ac9a67 always checkSource before accessing anything
like earlier, anything accessed during eval must be checked against the
list of path restrictions. this notably excludes `Pos::getSource` which
is run only from an unrestricted context (resolving line/column numbers
for expressions), but since positions require the parser to run and the
parser requires a checked input to produce positions this is not a leak

Change-Id: I337859e9c780590d4434885125a3ef70a11f6e93
2025-01-10 15:20:27 -08:00
eldritch horrorsandJade Lovelace 3f6a1e45c9 libexpr: always checkSourcePath in resolveExprPath
the purpose of resolveExprPath is to produce a parser input path. parser
input paths must be validated against the path allow list so they do not
escape the restricted/pure eval sandbox. checking the input path and any
intermediate paths during resolving makes this a lot harder to do badly.

Change-Id: Ib31b5bca63fe26a5e08458a871cdc9f92f9b6a10
2025-01-10 15:20:27 -08:00
eldritch horrorsandJade Lovelace ede0851fb4 libexpr: move resolveExprPath to EvalPaths
Change-Id: I4f8e27bb816d6498df4d73a57e10b654eb995c32
2025-01-10 15:20:27 -08:00
eldritch horrorsandJade Lovelace 5af069b248 libutil: remove SourcePath::resolveSymlinks
in pure mode it is entirely useless. in impure mode it's mostly useless
since the way in which it is used is either equivalent to not being run
at all, or is equivalent to turning the following lstat into a stat. we
add a stat method instead for all those who need final symlinks stat'd.

Change-Id: I801886d18eb34b26e62b4c05d53318c6421a69bf
2025-01-10 15:20:27 -08:00
eldritch horrorsandJade Lovelace f93af1db1f libutil: make SourcePath::path private
use canonical() to get the disk path, to_string() to get the string form.

Change-Id: I95bb6df53356f30290b487d1cca0aa2fb37249ed
2025-01-10 15:20:27 -08:00
eldritch horrorsandJade Lovelace 3acba7951a libexpr: use StorePath::to_string in string contexts
`path.abs()` does the same thing, but `to_string` communicates intent as well.

Change-Id: I9619a9f2e32317f0a1cc8e092ce8898471b980ac
2025-01-10 15:20:27 -08:00
eldritch horrorsandJade Lovelace 44255c316d libutil: remove SourcePath::getPhysicalPath
all files are physical, so this doesn't have to be optional. if it only
returns a copy of a member it's not useful either, but performance cost

Change-Id: Ib2f935ae247d96418d55bc100e04765dc586528b
2025-01-10 15:20:27 -08:00
jadeandGerrit Code Review d953e138a2 Merge "fix: macOS build broken on nixos-unstable" into main 2025-01-10 22:23:14 +00:00
eldritch horrors fafe647bc2 libstore: fix UAF in FileTransfer
after startTransfer the transfer, and thus downloadState, is gone. asan
hasn't caught this, presumably because the access is in libc somewhere.
we don't even need access to the old state; the assertion is not useful
here and clearing the previous exception is invisible to the new round.

Change-Id: I32dc1a487b96cbaabcf5061c9b1f96dbc5aaae49
2025-01-10 17:05:02 +01:00
Jade Lovelace 37e8904ba7 fix: macOS build broken on nixos-unstable
This is definitely a bug in rapidcheck but also rapidcheck is
unmaintained (author vanished) so we can't really do anything about it
on that side.

lix> FAILED: tests/unit/liblixutil-test-support.dylib.p/libutil-support_tests_hash.cc.o
lix> clang++ -Itests/unit/liblixutil-test-support.dylib.p -Itests/unit -I../tests/unit -I../tests/unit/libutil-support -I. -I.. -Ilix/libutil -Ilix/libexpr -fdiagnostics-color=always -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST -Wall -Winvalid-pch -Wextra -std=c++23 -O2 -g -fpch-instantiate-templates -include config.h -Wno-unused-parameter -Wno-deprecated-declarations -Wno-missing-field-initializers -Wimplicit-fallthrough -Werror=switch -Werror=switch-enum -Werror=unused-result -Wdeprecated-copy -Wignored-qualifiers -Werror=suggest-override -fsanitize=signed-integer-overflow -fsanitize-undefined-trap-on-error -ffile-prefix-map=../lix=lix -MD -MQ tests/unit/liblixutil-test-support.dylib.p/libutil-support_tests_hash.cc.o -MF tests/unit/liblixutil-test-support.dylib.p/libutil-support_tests_hash.cc.o.d -o tests/unit/liblixutil-test-support.dylib.p/libutil-support_tests_hash.cc.o -c ../tests/unit/libutil-support/tests/hash.cc
lix> In file included from ../tests/unit/libutil-support/tests/hash.cc:3:
lix> In file included from /nix/store/k8b7wc0lkr3lqxybzv458ijddpqnzlgw-rapidcheck-0-unstable-2023-12-14-dev/include/rapidcheck.h:18:
lix> In file included from /nix/store/k8b7wc0lkr3lqxybzv458ijddpqnzlgw-rapidcheck-0-unstable-2023-12-14-dev/include/rapidcheck/Gen.h:74:
lix> /nix/store/k8b7wc0lkr3lqxybzv458ijddpqnzlgw-rapidcheck-0-unstable-2023-12-14-dev/include/rapidcheck/Gen.hpp:72:22: error: calling 'current_exception' with incomplete return type 'exception_ptr'
lix>    72 |     auto exception = std::current_exception();
lix>       |                      ^~~~~~~~~~~~~~~~~~~~~~~~
lix> /nix/store/0nhi47d5ip48wprxnava6vv973zzzndf-libcxx-19.1.5-dev/include/c++/v1/__exception/operations.h:37:41: note: 'current_exception' declared here
lix>    37 | _LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT;
lix>       |                                         ^
lix> /nix/store/0nhi47d5ip48wprxnava6vv973zzzndf-libcxx-19.1.5-dev/include/c++/v1/__exception/operations.h:35:33: note: forward declaration of 'std::exception_ptr'
lix>    35 | class _LIBCPP_EXPORTED_FROM_ABI exception_ptr;
lix>       |                                 ^
lix> 1 error generated.

Change-Id: Id5d0c4aa8143f2469c5a636d6773a2f5a25a0268
2025-01-07 17:11:04 -08:00
piegamesandGerrit Code Review 3413ab5629 Merge "libexpr: Undeprecate overriding __findFile" into main 2025-01-07 18:39:48 +00:00
Maximilian Bosch a1c09bed7b libstore: fix "illegal reference specifier 'man'"-error in postgresql_14
Nixpkgs issues / PRs:
* https://github.com/NixOS/nixpkgs/pull/368091
* https://github.com/NixOS/nixpkgs/issues/369366

This can be triggered with the postgresql_14 derivation from nixpkgs rev
19305d94dacca226ca048b78e6de00f599c65858
(/nix/store/bxp6g57limvwiga61vdlyvhy7i8rp6wd-postgresql-14.15.drv on
x86_64-linux): for reasons unknown to me, only the `man` and `lib` outputs
are cached on cache.nixos.org:

    $ nix derivation show  /nix/store/bxp6g57limvwiga61vdlyvhy7i8rp6wd-postgresql-14.15.drv | jq '.[].outputs.[].path' -r | xargs nix path-info --store https://cache.nixos.org
    warning: The interpretation of store paths arguments ending in `.drv` recently changed. If this command is now failing try again with '/nix/store/bxp6g57limvwiga61vdlyvhy7i8rp6wd-postgresql-14.15.drv^*'
    don't know how to build these paths:
      /nix/store/m9vb40xxr6gckjzpfxnqcmjqsks2gx03-postgresql-14.15
      /nix/store/nm1415wa53iawar9axwxy0an6ximhayn-postgresql-14.15-dev
      /nix/store/v9vrvfhiw9gk8hj9895sb15fxvxnyylj-postgresql-14.15-debug
      /nix/store/zi12g1p99g2173i8093ixbqkfh9ng87b-postgresql-14.15-doc
    /nix/store/3i3fpz0xss9inampf51gp3pkx24ypxpj-postgresql-14.15-man
    /nix/store/db8797h2cp4rm1cnsqrf87apkkxwwdff-postgresql-14.15-lib
    error: path '/nix/store/m9vb40xxr6gckjzpfxnqcmjqsks2gx03-postgresql-14.15' does not exist in the store

Also, the derivation uses the `outputChecks` feature (and thus `__structuredAttrs`)
to make sure that e.g. the `out` output doesn't reference the `man`
output:

    __structuredAttrs = true;
    outputs = [ "out" "dev" "doc" "lib" "man" ];
    outputChecks.out.disallowedReferences = [ "dev" "doc" "man" ];

With all that in place, the following error was hit on all CppNix / Lix
versions currently supported when trying to build the derivation above:

    error: derivation contains an illegal reference specifier 'man'

The following happened here:

* The `man` & `lib` outputs were substituted at some point.
* When register outputs, the reference checks are made.
* `LocalDerivationGoal::checkOutputs` gets a map of all outputs that
  were built and are NOT already registered in the store. In the example
  above this means `out`, `dev`, `debug` and `doc`.
* `checkOutputs` tries to resolve the `man` output and fails to do so
  because it's a store-path that's already registered and thus not part
  of the map passed to `checkOutputs`.

Since the map passed to `checkOutputs` is used in various other places
that appear to assume that the paths aren't registered already, I didn't
write the already registered paths into it. Instead, I created a second
map that contains all already registered outputs and pass it as third
argument to `checkOutputs`. If the other lookups fail, this map will be
now checked before the "illegal reference specifier"-error is thrown.

This fixes the problem with `postgresql_14` for me.

Also wrote a small regression test that fails locally without the patch
in place.

Change-Id: Ieacca80c001fcfbebf6f5fe97e25c49d2724c3ff
2025-01-05 14:50:45 +01:00
eldritch horrors 8c1ece93cc libstore: fix download deadlock on interruption
in a daemon all calls to the logger can throw an Interrupted exception,
which so far has silently stopped the curl thread without notifying its
transfers and leaving them stuck as a result. ensuring that the loggers
can never throw Interrupted will have very unpleasant side-effects, and
throwing depending on context requires large amount of bookkeeping. for
now it is easiest to abort all transfers on Interrupted during cleanup.

the test for this is extremely sketchy because we want to hit a single,
very specifically chosen, loger call in TransferItem::finish(). the bug
was triggered by the `act.progress` further down from what we're aiming
for, but that one is much harder to select for than the debug log here.

fixes #613

Change-Id: Id72efa64dd30cbbf256d2ab2a328457a0b095c6a
2025-01-05 01:19:12 +01:00
eldritch horrors c314c5e581 benchmarks: fix config for nixos 24.11
the flake input bump broke these due to packages being moved. also fix
renamed options while we are here, before they inevitably break later.

Change-Id: If16bb0a221e63ae7394af6b8d904c5ecd8994e6f
2025-01-05 01:19:12 +01:00
eldritch horrors 6e8bc92ca5 flake: fix nixpkgs lib test
the bump to 24.11 broke this, and buildbot simply ignored it. great.

Change-Id: I9a6c177c0679beb87891c05c34272c6c437c65fa
2025-01-05 01:19:12 +01:00
piegames 539c340c66 libexpr: Undeprecate overriding __findFile
After gathering more community feedback, more non-trivial use cases for
overriding `__findFile` emerged. Unlike the use case of Tvix mentioned
in #599, these can't easily be worked around by overriding `nixPath`
instead.

This is the second fixup/partial revert for
81d5f0a7d9.
See also #599.

Change-Id: I7ca75e1a2b196c0da341969c61f4c168b5f657f9
2025-01-04 19:07:35 +01:00
Chip Bilbrey 5c7ea4f446 Use locked flake-compat in shell.nix
Change-Id: I059aa6da6365f1a5a46b506e57d9b3ab2b73d8d8
2024-12-30 07:25:23 -08:00
Yureka 92ed9fee7d fix(libstore): correctly trigger embedded sandbox shell logic
Change-Id: I8131c7a94b3cd54d7e75fcdddf2fb8d561b6e38f
2024-12-11 16:48:34 +01:00
V.andGerrit Code Review 4f5e5e9bdf Merge "refactor(libutil): add new constructor to SysError using std::error_code" into main 2024-12-11 08:44:38 +00:00
rebecca “wiggles” turnerandGerrit Code Review 06996718c3 Merge "repl: tab-complete quoted attribute names" into main 2024-12-11 03:27:15 +00:00
jadeandGerrit Code Review cb44fe7c15 Merge changes Ic890f781,I77b2de10,I3202aba0,I6ddc4296,I18776984, ... into main
* changes:
  doc: fix broken table in operators list
  terminal code eaters: implement OSC
  libexpr: significantly improve error messages for bad attr paths
  tests/functional2: add terminal code eater
  tests/functional2: fix occasional pytest haunting
  attr path parser: fix bug in not rejecting empty attr paths, add unparser
2024-12-11 02:28:11 +00:00
Ian ChamberlainandRebecca Turner 67f07e05df repl: tab-complete quoted attribute names
Attribute names containing special characters like @ or . need to be
quoted, so we need to do our own tokenization of the command line for
completion, and quote the attribute names when we provide the completion.

Fixes: https://git.lix.systems/lix-project/lix/issues/450

Change-Id: I55a30dd272880c89445d9ded49b3f2c90cb19326
2024-12-10 18:10:16 -08:00
beviuandRebecca Turner bc63b007e5 Mention support for ~/ paths in nix.conf in manual
Fixes: https://git.lix.systems/lix-project/lix/issues/497

Change-Id: I9606900d17f62359cef4fe2c8a01e5791390a870
2024-12-10 16:36:35 -08:00
Jade Lovelace f51943f171 doc: fix broken table in operators list
Fixes: https://git.lix.systems/lix-project/lix/issues/597
Change-Id: Ic890f781af10fbcab23deae5ab9c10eebfbab070
2024-12-10 15:43:31 -08:00
Jade Lovelace 5530de4673 terminal code eaters: implement OSC
This is a useful piece of functionality to being able to eat URL
hyperlinks, for instance, which is a bug that Lix has while dealing with
terminal output today.

Change-Id: I77b2de107b2525cad7ea5dea28bfba2cc78b9e6d
2024-12-10 15:43:31 -08:00
Jade Lovelace faf00ad022 libexpr: significantly improve error messages for bad attr paths
This commit makes Lix include the summarized content of the value being
indexed when it is bad.

lix/lix2 » nix eval --expr '{x.y = 2;}' 'x.y.z'
error: the value being indexed in the selection path 'x.y.z' at 'x.y' should be a set but is an integer: 2

lix/lix2 » nix eval --expr '{x.y = { a = 3; };}' 'x.y.z'
error: attribute 'z' in selection path 'x.y.z' not found inside path 'x.y', whose contents are: { a = 3; }
       Did you mean a?

lix/lix2 » nix eval --expr '{x.y = { a = 3; };}' 'x.y.1'
error: the expression selected by the selection path 'x.y.1' should be a list but is a set: { a = 3; }

Change-Id: I3202aba0e437e00b4c6d3ee287a2d9a7c6892dbf
2024-12-10 15:43:31 -08:00
Jade Lovelace c0808bd855 tests/functional2: add terminal code eater
I want this for being able to write reasonable expect-test style tests
for oneliners. We will still probably want something like insta for more
complicated test cases where you actually *want* the output in a
different file, but for now this will do.

cc: https://git.lix.systems/lix-project/lix/issues/595
Change-Id: I6ddc42963cc49177762cfca206fe9a9efe1ae65d
2024-12-10 15:43:31 -08:00
Jade Lovelace 93d5221b9b tests/functional2: fix occasional pytest haunting
I don't know what the heck the xonsh module is doing but its obviously
crimes so it has to go. It was never intended to be running here anyway.

Fixes: https://git.lix.systems/lix-project/lix/issues/593
Change-Id: I1877698469392f85884945aaa60987c68c4e0ebc
2024-12-10 13:32:28 -08:00
Jade Lovelace 21ad02c1d0 attr path parser: fix bug in not rejecting empty attr paths, add unparser
The following behaviour was previously present and has been fixed:

lix/lix2 » nix eval --expr '{x."" = 2;}' 'x.""'
{ "" = 2; }
lix/lix2 » nix eval --expr '{x."".y = 2;}' 'x."".y'
error: empty attribute name in selection path 'x."".y'

Change-Id: Iad21988f1191c33a3661c72a6b7f01a8b8b3e6eb
2024-12-10 13:32:28 -08:00
Jade Lovelace 8ddcdfb59c build: fix on x86_64-darwin
Lix requires a non-antiquated macOS SDK, and 24.11 does not yet have a
non-antiquated one as default.

Fixes: https://git.lix.systems/lix-project/lix/issues/588
Change-Id: Iad19c06d7fefe3a736cdcb39ced185e52dcfcbb8
2024-12-10 12:32:42 -08:00
Artemis TosiniandJade Lovelace 445b7c7d8a flake: Use nixpkgs 24.11
nixpkgs 24.11 changes how we access xonsh yet again
and updates clang.

Unfortunately, clang 18 produces significantly more
warnings on existing code that is challenging to fix.
Make sure that doesn't error when we're running
`-Werror` builds.

n.b. I had to change the "SSL certificate problem: self-signed
certificate" to the old error prior to the improved libcurl errors,
since what is presumably a difference in which TLS library is used has
cropped up between releases? Either way the curl error buffer is empty.
Seems like we aggressively cannot do anything about this.

Change-Id: If0141a46a8b445a0e7d6f86f939e8c8e03569bf5
2024-12-10 12:32:42 -08:00
jadeandGerrit Code Review 9a96086381 Merge "tree-wide: fix a pile of lints" into main 2024-12-10 20:29:53 +00:00
piegames 7c76053d93 libexpr: Undeprecate overriding __nixPath
It being overridable was an intended feature with good use cases, and
should not have been removed. However, this feature is generally in a
bad state and needs revisiting in the future.

Fixup for 81d5f0a7d9
Fixes #599

Change-Id: I2d93e012caa65aa795bce3a71d8e56d7052ef9df
2024-12-10 19:02:41 +01:00
vigress8 95e088de72 refactor(libutil): add new constructor to SysError using std::error_code
Change-Id: I6150d7966442551f0b6f7a0cc9739a4f9d6c4e7e
2024-12-09 20:43:40 +04:00
piegamesandGerrit Code Review 369e3f82f0 Merge changes I4771fe87,Ifc7a9516,I1f5e05ab,I63f2fbcd into main
* changes:
  libexpr: Rework error messages on ExprSelct::eval
  libexpr: Track position information in attrpaths
  libexpr: Assert: Don't print assertion in error message
  libexpr: Split ExprAttrs and ExprLet
2024-12-09 10:28:22 +00:00
piegames a2ae14bfd8 libexpr: Rework error messages on ExprSelct::eval
Calls to `show` have been removed. To counter the loss of information,
the error positions have been improved and now correctly point to the
current selector instead of the entire select expression.

Change-Id: I4771fe874af1ac15828a9863550cd4369a8f0e94
2024-12-08 20:52:18 +01:00
piegames 172515bd8b libexpr: Track position information in attrpaths
This is a pretty small change because the parser already has all
necessary information (needed for parse errors), now we want to keep it
to also provide better eval errors.

Change-Id: Ifc7a9516b9b0c8d9698f1899a6912ae91f6696ab
2024-12-08 20:51:45 +01:00
piegames cdda2454f6 libexpr: Assert: Don't print assertion in error message
The `show` functionality needs to be removed because it is deeply
flawed, and given that we already print position information in the
error message (which probably wasn't always the case in the past) the
assertion printing is redundant anyways.

Change-Id: I1f5e05ab73aaa0ec92994c2211463260fd374898
2024-12-08 20:51:44 +01:00
sethandeldritch horrors f7687fa414 libstore/linux: include sys/syscall.h
Per `seccomp(2)`, this header defines the `SYS_*` constants used

Found in https://github.com/NixOS/nixpkgs/pull/353576

Change-Id: I64ebc5513c53500b7a9012eaa664c2e59f49ceac
2024-12-08 18:49:27 +00:00
piegamesandeldritch horrors 9611018c27 libexpr: Split ExprAttrs and ExprLet
ExprLet was previously inheriting from ExprAttrs for the data, while
ignoring all
set-specific operations on it. The set specific code has now been split
off so that
let doesn't inherit it anymore:

- ExprAttrs (not an Expr), containing the attributes and the related
logic
- ExprLet : Expr, ExprAttrs
- ExprSet : Expr, ExprAttrs

Co-authored-by: eldritch horrors <pennae@lix.systems>
Change-Id: I63f2fbcd1e790b3cffb56eec1e7565ee3cdbf964
2024-12-08 12:54:38 +01:00