JSON mode was accepted by single-ID verbs but still printed bare IDs.
Print JSON objects for those verbs and reject ambiguous JSON combinations.
Follow-up for: a50666e376.
I am really not a fan of full code lines passed to macros as parameters.
Let's get rid of the 3rd parameter of FOREACH_OPTION() hence:
1. Let's return errors just as a regular value (though a negative one),
that can be handled via a OPTION_ERROR case statement for the switch.
This normalizes handling of the error, just like any other event
returned by the option parser.
2. In order to avoid exploding the amount of boilerplate in each use
(that just propagates the error on OPTION_ERROR), let's then
introduce an explicit FOREACH_OPTION_OR_RETURN(), that returns from
the calling function on its own (and makes that clear in the name).
Together this cleans up, normalizes the logic and shortens the code.
It was requested to make the 'c', 'opt', and 'arg' params the same, i.e.
defined through the FOREACH_OPTION macro. But we can't do that easily,
because 'c' was defined in the for loop definition, and we can only
define variables of the same type in that way. Also, in some cases we
need only 'c', in other cases with need 'c' and 'arg, in some cases 'c'
and 'opt', and in other cases all three. We'd need to either
conditionalize or mark those variables with _unused_ to deal with
compiler warnings. But a different approach works quite nicely: add
state.opt and state.arg to show the current option and it's argument.
(The short names are picked on purpose to reduce verbosity since those
are used a lot.)
We generally want to print an error message if table_print()
fails. Add a helper function for this and use it consistently.
This does one of the three things depending on the call site:
- a no-change reformatting of the code
- change from a custom message to the generic one
- addition of the error message where previously none was printed
In the third case, the actual use impact is very small, since the
table formatting is very unlikely to fail. But if it did, we would
often return an error without any message whatsoever, which we
never want to do.
Almost all callers of table_print() specify stdout or NULL (equivalent
to stdout) as the output stream. Simplify things by not requiring the
the stream to be specified.
In almost all cases, the printing of the table is surrounded by normal
printfs() that don't do explicit flushing and for which we don't check
the output stream status. Let's simplify most callers and skip this
step. The reason is not so much to avoid the extra step itself, but
instead to avoid the _handling_ of the potential failure. We generally
only want to print an error message for ENOMEM and other "internal"
errors, so strictly speaking we should filter out the errors from the
stream. By skipping the flush&check step we implicitly do this.
The column index is moved to the first position. I think we're unlikely
to want to synchronize widths of *different* columns, and having just
one column argument makes the callers simpler. Also, the type is changed
to size_t to match other functions, and this avoids the need to cast
to size_t in the callers.
After writing the code to parse options in a bunch of places, I think
passing the argc+argv to various functions to query state is annoying.
It seems nicer to just stash them in the state struct once.
This feel a bit like a hack, but it works OK. The width of the first
column of verbs or options in different sections is measured and
applied to the other tables. This makes the second column aligned.
We often have a pattern where the same verb function is used for
multiple actions. This leads to an antipattern where we figure out what
action needs to be taken from argv[0] multiple times: often once in
parse_argv() to figure out what options are allowed, then once again
implicitly in dispatch_verb(), and then again in the action verb itself.
Let's allow passing a parameter into the verb to simplify this.
This matches a pattern we have in conf-parser.h, where we have both
void *userdata (more global) and void *data (per-config item). Here,
I opted for uintptr_t userdata. It seems that most of the time we'll
want to just pass an enum value. This works OK with no casts. I also
tried a void* and union. In both cases, much more boilerplate is needed:
either a cast or a macro to help avoid compiler warnings. uintptr_t
seems generic enough to cover foreseeable usecases with no fuss.
This is a noop refactoring. See next commit for an example.
This commit cleans up the includes for all the small tools across
the tree.
A few cases of returning EXIT_SUCCESS are replaced with returning
0 to avoid including <stdlib.h>.
Split out of #37344.
Now that the necessary functions from log.h have been moved to macro.h,
we can stop including log.h in macro.h. This requires modifying source
files all over the tree to include log.h instead.
As per DPS the UUID for /var/ should be keyed by the local machine-id,
which is non-trivial to do in a script. Enhance 'systemd-id128' to
take 'var-partition-uuid' as a verb, and if so perform the
calculation.
Prompted by #33737
The intention of b37e8184a5
is to expose sd_id128_get_app_specific() on command line.
But combining that with GPT type list makes little sense.
This is preparation for making our Varlink API a public API. Since our
Varlink API is built on top of our JSON API we need to make that public
first (it's a nice API, but JSON APIs there are already enough, this is
purely about the Varlink angle).
I made most of the json.h APIs public, and just placed them in
sd-json.h. Sometimes I wasn't so sure however, since the underlying data
structures would have to be made public too. If in doubt I didn#t risk
it, and moved the relevant API to src/libsystemd/sd-json/json-util.h
instead (without any sd_* symbol prefixes).
This is mostly a giant search/replace patch.
If it is null, we get the 'base' param unchanged:
$ build/systemd-id128 show 00000000000000000000000000000001 \
--app-specific=00000000000000000000000000000000
00000000000000000000000000000001
This is not good, because it breaks our promise that the base (usually either
machine-id or boot-id) cannot be derived from the result. Some application
using the library could use a null app id, inadvertently exposing the machine
or boot id. (This could happen because of forgotten initialization, or maybe
because the app id is configurable, and the user configures it wrongly.)
Note: the other way the secret is not exposed:
$ build/systemd-id128 show 00000000000000000000000000000000 \
--app-specific=00000000000000000000000000000002
4f63080959264900b0d88d999dae2d3a
Normally systemd would not allow a null machine-id or boot-id, but we can let
the user do the calculation that if they want to.
https://github.com/systemd/systemd/issues/27514 requested this functionality
among other things, but it is already implemented. The man page was also
missing 'show' in the synopsis, so add that, along with an example.
Instead of exposing just the partition type UUID, let's expose the
GptPartitionType struct, which has a lot more information available
in a much more accessible way.
Also, let's get rid of SECONDARY/OTHER in PartitionDesignator. These
were only there to support preferred architectures in dissect-image.c,
but we can easily handle that by comparing architectures when we decide
whether to override a partition. This is done in a new function
compare_arch().
In general we almost never hit those asserts in production code, so users see
them very rarely, if ever. But either way, we just need something that users
can pass to the developers.
We have quite a few of those asserts, and some have fairly nice messages, but
many are like "WTF?" or "???" or "unexpected something". The error that is
printed includes the file location, and function name. In almost all functions
there's at most one assert, so the function name alone is enough to identify
the failure for a developer. So we don't get much extra from the message, and
we might just as well drop them.
Dropping them makes our code a tiny bit smaller, and most importantly, improves
development experience by making it easy to insert such an assert in the code
without thinking how to phrase the argument.
I think this formatting was originally used because it simplified
adding new options to the help messages. However, these days, most
tools their help message end with "\nSee the %s for details.\n" so
the final line almost never has to be edited which eliminates the
benefit of the custom formatting used for printf() help messages.
Let's make things more consistent and use the same formatting for
printf() help messages that we use everywhere else.
Prompted by https://github.com/systemd/systemd/pull/18355#discussion_r567241580
Presently, CLI utilities such as systemctl will check whether they have a tty
attached or not to decide whether to parse /proc/cmdline or EFI variable
SystemdOptions looking for systemd.log_* entries.
But this check will be misleading if these tools are being launched by a
daemon, such as a monitoring daemon or automation service that runs in
background.
Make log handling of CLI tools uniform by never checking /proc/cmdline or EFI
variables to determine the logging level.
Furthermore, introduce a new log_setup_cli() shortcut to set up common options
used by most command-line utilities.
The tool deals with any kind of 128bit id, not just uuid, and by default
we display just a series of hex chars, hence let's not claim everything
was a "uuid", but just generically say "id"
Was getting:
../src/id128/id128.c:15:1: error: initializer element is not constant
static sd_id128_t arg_app = SD_ID128_NULL;
^
when building on CentOS 7.
Other parts of the code initialize `static sd_id128_t` to {} and this
was the original setting before a19fdd66c2 anyways.
For some unrelated stuff I wanted the machine ID in UUID format, and it
was annoying doing that manually. So let's add a switch for this, so
that this works:
systemd-id128 machine-id -u
When emitting the calendarspec warning we want to see some color.
Follow-up for 04220fda5c.
Exceptions:
- systemctl, because it has a lot hand-crafted coloring
- tmpfiles, sysusers, stdio-bridge, etc, because they are also used in
services and I'm not sure if this wouldn't mess up something.
This way, we can extend the macro a bit with stuff pulled in from other
headers without this affecting everything which pulls in macro.h, which
is one of our most basic headers.
This is just refactoring, no change in behaviour, in prepartion for
later changes.
The raison d'etre for this program is printing machine-app-specific IDs. We
provide a library function for that, but not a convenient API. We can hardly
ask people to quickly hack their own C programs or call libsystemd through CFFI
in python or another scripting language if they just want to print an ID.
Verb 'new' was already available as 'journalctl --new-id128', but this makes
it more discoverable.
v2:
- rename binary to systemd-id128
- make --app-specific= into a switch that applies to boot-id and machine-id