mirror of
https://github.com/systemd/systemd
synced 2026-03-14 09:04:47 +01:00
Compare commits
No commits in common. "37ef2fc9f7709c710692081e7e3be94d7b16d9fa" and "2a9cfe6b07c41a88b57813afc4f73f4332ac74d2" have entirely different histories.
37ef2fc9f7
...
2a9cfe6b07
9
TODO
9
TODO
@ -50,6 +50,12 @@ Features:
|
||||
* systemd-sysext: optionally, run it in initrd already, before transitioning
|
||||
into host, to open up possibility for services shipped like that.
|
||||
|
||||
* add a flag to the GPT spec that says "grow my fs to partition size", and make
|
||||
it settable via systemd-repart. Add in growfs jobs in
|
||||
systemd-gpt-auto-generator when it is set, and issue the ioctls while
|
||||
mounting in systemd-npsawn --image=. That way systemd-repart suffices to
|
||||
enlarge an image.
|
||||
|
||||
* add a new switch --auto-definitions=yes/no or so to systemd-repart. If
|
||||
specified, synthesize a definition automatically if we can: enlarge last
|
||||
partition on disk, but only if it is marked for growing and not read-only.
|
||||
@ -349,6 +355,9 @@ Features:
|
||||
* busctl: maybe expose a verb "ping" for pinging a dbus service to see if it
|
||||
exists and responds.
|
||||
|
||||
* systemd-gpt-auto should probably set x-systemd.growfs on the mounts it
|
||||
creates
|
||||
|
||||
* bootctl:
|
||||
- teach it to prepare an ESP wholesale, i.e. with mkfs.vfat invocation
|
||||
- teach it to copy in unified kernel images and maybe type #1 boot loader spec entries from host
|
||||
|
||||
@ -94,48 +94,24 @@ localized.
|
||||
|
||||
## Partition Flags
|
||||
|
||||
This specification defines three GPT partition flags that may be set for the
|
||||
partition types defined above:
|
||||
For the root, `/usr/`, server data, home, variable data, temporary data and swap
|
||||
partitions, the partition flag bit 63 ("*no-auto*") may be used to turn off
|
||||
auto-discovery for the specific partition. If set, the partition will not be
|
||||
automatically mounted or enabled.
|
||||
|
||||
1. For the root, `/usr/`, Verity, home, server data, variable data, temporary data,
|
||||
swap and extended boot loader partitions, the partition flag bit 63
|
||||
("*no-auto*") may be used to turn off auto-discovery for the specific
|
||||
partition. If set, the partition will not be automatically mounted or
|
||||
enabled.
|
||||
For the root, `/usr/`, server data, home, variable data and temporary data
|
||||
partitions, the partition flag bit 60 ("*read-only*") may be used to mark a
|
||||
partition for read-only mounts only. If set, the partition will be mounted
|
||||
read-only instead of read-write. Note that the variable data partition and the
|
||||
temporary data partition will generally not be able to serve their purpose if
|
||||
marked read-only, since by their very definition they are supposed to be
|
||||
mutable. (The home and server data partitions are generally assumed to be
|
||||
mutable as well, but the requirement for them is not equally strong.) Because
|
||||
of that, while the read-only flag is defined and supported, it's almost never a
|
||||
good idea to actually use it for these partitions.
|
||||
|
||||
2. For the root, `/usr/`, Verity, home, server data, variable data, temporary
|
||||
data and extended boot loader partitions, the partition flag bit 60
|
||||
("*read-only*") may be used to mark a partition for read-only mounts only.
|
||||
If set, the partition will be mounted read-only instead of read-write. Note
|
||||
that the variable data partition and the temporary data partition will
|
||||
generally not be able to serve their purpose if marked read-only, since by
|
||||
their very definition they are supposed to be mutable. (The home and server
|
||||
data partitions are generally assumed to be mutable as well, but the
|
||||
requirement for them is not equally strong.) Because of that, while the
|
||||
read-only flag is defined and supported, it's almost never a good idea to
|
||||
actually use it for these partitions. Also note that Verity partitions are
|
||||
by their semantics always read-only. The flag is hence of little effect for
|
||||
them, and it is recommended to set it unconditionally for the Verity
|
||||
partition types.
|
||||
|
||||
3. For the root, `/usr/`, home, server data, variable data, temporary data and
|
||||
extended boot loader partitions, the partition flag bit 59
|
||||
("*grow-file-system*") may be used to mark a partition for automatic growing
|
||||
of the contained file system to the size of the partition when
|
||||
mounted. Tools that automatically mount disk image with a GPT partition
|
||||
table are suggested to implicitly grow the contained file system to the
|
||||
partition size they are contained in. This flag is without effect on
|
||||
partitions marked read-only.
|
||||
|
||||
Note that the first two flag definitions happen to map nicely to the ones used
|
||||
by Microsoft Basic Data Partitions.
|
||||
|
||||
All three of these flags generally affect only auto-discovery and automatic
|
||||
mounting of disk images. If partitions marked with these flags are mounted
|
||||
using low-level commands like
|
||||
[mount(8)](https://man7.org/linux/man-pages/man2/mount.8.html) or directly with
|
||||
[mount(2)](https://man7.org/linux/man-pages/man2/mount.2.html), they typically
|
||||
have no effect.
|
||||
Note that these two flag definitions happen to map nicely to the ones used by
|
||||
Microsoft Basic Data Partitions.
|
||||
|
||||
## Suggested Mode of Operation
|
||||
|
||||
|
||||
@ -354,40 +354,10 @@ Fri … 552351 1000 1000 SIGSEGV present /usr/lib64/firefox/firefox 28.7M
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<title>Show information about a core dump matched by PID</title>
|
||||
<title>Show information about a process that dumped core,
|
||||
matching by its PID 6654</title>
|
||||
|
||||
<programlisting>$ coredumpctl info 6654
|
||||
PID: 6654 (bash)
|
||||
UID: 1000 (user)
|
||||
GID: 1000 (user)
|
||||
Signal: 11 (SEGV)
|
||||
Timestamp: Mon 2021-01-01 00:00:01 CET (20s ago)
|
||||
Command Line: bash -c $'kill -SEGV $$'
|
||||
Executable: /usr/bin/bash
|
||||
Control Group: /user.slice/user-1000.slice/…
|
||||
Unit: user@1000.service
|
||||
User Unit: vte-spawn-….scope
|
||||
Slice: user-1000.slice
|
||||
Owner UID: 1000 (user)
|
||||
Boot ID: …
|
||||
Machine ID: …
|
||||
Hostname: …
|
||||
Storage: /var/lib/systemd/coredump/core.bash.1000.….zst (present)
|
||||
Disk Size: 51.7K
|
||||
Message: Process 130414 (bash) of user 1000 dumped core.
|
||||
|
||||
Stack trace of thread 130414:
|
||||
#0 0x00007f398142358b kill (libc.so.6 + 0x3d58b)
|
||||
#1 0x0000558c2c7fda09 kill_builtin (bash + 0xb1a09)
|
||||
#2 0x0000558c2c79dc59 execute_builtin.lto_priv.0 (bash + 0x51c59)
|
||||
#3 0x0000558c2c79709c execute_simple_command (bash + 0x4b09c)
|
||||
#4 0x0000558c2c798408 execute_command_internal (bash + 0x4c408)
|
||||
#5 0x0000558c2c7f6bdc parse_and_execute (bash + 0xaabdc)
|
||||
#6 0x0000558c2c85415c run_one_command.isra.0 (bash + 0x10815c)
|
||||
#7 0x0000558c2c77d040 main (bash + 0x31040)
|
||||
#8 0x00007f398140db75 __libc_start_main (libc.so.6 + 0x27b75)
|
||||
#9 0x0000558c2c77dd1e _start (bash + 0x31d1e)
|
||||
</programlisting>
|
||||
<programlisting>$ coredumpctl info 6654</programlisting>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
|
||||
@ -51,13 +51,6 @@
|
||||
ordered by their metric. This assigns a stable hostname to the
|
||||
current gateway, useful for referencing it independently of the
|
||||
current network configuration state.</para></listitem>
|
||||
|
||||
<listitem><para>The hostname <literal>_outbound</literal> is resolved to the local IPv4 and IPv6
|
||||
addresses that are most likely used for communication with other hosts. This is determined by
|
||||
requesting a routing decision to the configured default gateways from the kernel and then using the
|
||||
local IP addresses selected by this decision. This hostname is only available if there is at least one
|
||||
local default gateway configured. This assigns a stable hostname to the local outbound IP addresses,
|
||||
useful for referencing them independently of the current network configuration state.</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>Various software relies on an always-resolvable local
|
||||
|
||||
@ -55,13 +55,11 @@
|
||||
partition slot greater than the highest slot number currently in use. Any existing partitions that have
|
||||
no matching partition file are left as they are.</para>
|
||||
|
||||
<para>Note that these definitions may only be used to create and initialize new partitions or to grow
|
||||
<para>Note that these definitions may only be used to created and initialize new partitions or grow
|
||||
existing ones. In the latter case it will not grow the contained files systems however; separate
|
||||
mechanisms, such as
|
||||
<citerefentry><refentrytitle>systemd-growfs</refentrytitle><manvolnum>8</manvolnum></citerefentry> may be
|
||||
used to grow the file systems inside of these partitions. Partitions may also be marked for automatic
|
||||
growing via the <varname>GrowFileSystem=</varname> setting, in which case the file system is grown on
|
||||
first mount by tools that respect this flag. See below for details.</para>
|
||||
used to grow the file systems inside of these partitions.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
@ -582,39 +580,13 @@
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>ReadOnly=</varname></term>
|
||||
<term><varname>GrowFileSystem=</varname></term>
|
||||
|
||||
<listitem><para>Configures the Read-Only and Grow-File-System partition flags (bit 60 and 59) of the
|
||||
partition table entry, as defined by the <ulink
|
||||
url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable Partitions Specification</ulink>. Only
|
||||
available for partition types supported by the specification. This option is a friendly way to set bit
|
||||
60 and 59 of the partition flags value without setting any of the other bits, and may be set via
|
||||
<varname>Flags=</varname> too, see above.</para>
|
||||
<listitem><para>Configures the Read-Only partition flags (bit 60) of the partition table entry. This
|
||||
option is a friendly way to set bit 60 of the partition flags value without setting any of the other
|
||||
bits, and may be set via <varname>Flags=</varname> too, see above.</para>
|
||||
|
||||
<para>If <varname>Flags=</varname> is used in conjunction with one or both of
|
||||
<varname>ReadOnly=</varname>/<varname>GrowFileSystem=</varname> the latter control the value of the
|
||||
relevant flags, i.e. the high-level settings
|
||||
<varname>ReadOnly=</varname>/<varname>GrowFileSystem=</varname> override the low-level setting
|
||||
<varname>Flags=</varname>.</para>
|
||||
|
||||
<para>Note that the two flags affect only automatic partition mounting, as implemented by
|
||||
<citerefentry><refentrytitle>systemd-gpt-auto-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
or the <option>--image=</option> option of various commands (such as
|
||||
<citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>). It
|
||||
has no effect on explicit mounts, such as those done via <citerefentry
|
||||
project='man-pages'><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry> or
|
||||
<citerefentry
|
||||
project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry></para>
|
||||
|
||||
<para>If both bit 50 and 59 are set for a partition (i.e. the partition is marked both read-only and
|
||||
marked for file system growing) the latter is typically without effect: the read-only flag takes
|
||||
precedence in most tools reading these flags, and since growing the file system involves writing to
|
||||
the partition it is consequently ignored.</para>
|
||||
|
||||
<para><varname>ReadOnly=</varname> defaults to on for Verity partition
|
||||
types. <varname>GrowFileSystem=</varname> defaults to on for all partition types that support it,
|
||||
except if the partition is marked read-only (and thus effectively, defaults to off for Verity
|
||||
partitions).</para></listitem>
|
||||
<para>If both <varname>Flags=</varname> and <varname>ReadOnly=</varname> are set the latter controls
|
||||
the value of the flag.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
@ -299,11 +299,11 @@
|
||||
|
||||
<listitem><para>Takes a boolean parameter; used in conjunction with <command>query</command>. If true
|
||||
(the default), select domains are resolved on the local system, among them
|
||||
<literal>localhost</literal>, <literal>_gateway</literal> and <literal>_outbound</literal>, or
|
||||
entries from <filename>/etc/hosts</filename>. If false these domains are not resolved locally, and
|
||||
either fail (in case of <literal>localhost</literal>, <literal>_gateway</literal> or
|
||||
<literal>_outbound</literal> and suchlike) or go to the network via regular DNS/mDNS/LLMNR lookups
|
||||
(in case of <filename>/etc/hosts</filename> entries).</para></listitem>
|
||||
<literal>localhost</literal> and <literal>_gateway</literal> or entries from
|
||||
<filename>/etc/hosts</filename>. If false these domains are not resolved locally, and either fail (in
|
||||
case of <literal>localhost</literal> or <literal>_gateway</literal> and suchlike) or go to the
|
||||
network via regular DNS/mDNS/LLMNR lookups (in case of <filename>/etc/hosts</filename>
|
||||
entries).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
||||
@ -194,28 +194,6 @@
|
||||
<option>--fsck=no</option>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--growfs=no</option></term>
|
||||
|
||||
<listitem><para>Turn off automatic growing of accessed file systems to their partition size, if
|
||||
marked for that in the GPT partition table. By default when an image is accessed for writing (by
|
||||
<option>--mount</option> or <option>--copy-to</option>) the file systems contained in the OS image
|
||||
are automatically grown to their partition sizes, if bit 59 in the GPT partition flags is set for
|
||||
partition types that are defined by the <ulink
|
||||
url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable Partitions Specification</ulink>. This
|
||||
behavior may be switched off using <option>--growfs=no</option>. File systems are grown automatically
|
||||
on access if all of the following conditions are met:</para>
|
||||
<orderedlist>
|
||||
<listitem><para>The file system is mounted writable</para></listitem>
|
||||
<listitem><para>The file system currently is smaller than the partition it is contained in (and thus can be grown)</para></listitem>
|
||||
<listitem><para>The image contains a GPT partition table</para></listitem>
|
||||
<listitem><para>The file system is stored on a partition defined by the Discoverable Partitions Specification</para></listitem>
|
||||
<listitem><para>Bit 59 of the GPT partition flags for this partition is set, as per specification</para></listitem>
|
||||
<listitem><para>The <option>--growfs=no</option> option is not passed.</para></listitem>
|
||||
</orderedlist>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--mkdir</option></term>
|
||||
|
||||
|
||||
@ -104,13 +104,6 @@
|
||||
gateway addresses, ordered by their metric. This assigns a stable hostname to the current gateway,
|
||||
useful for referencing it independently of the current network configuration state.</para></listitem>
|
||||
|
||||
<listitem><para>The hostname <literal>_outbound</literal> is resolved to the local IPv4 and IPv6
|
||||
addresses that are most likely used for communication with other hosts. This is determined by
|
||||
requesting a routing decision to the configured default gateways from the kernel and then using the
|
||||
local IP addresses selected by this decision. This hostname is only available if there is at least one
|
||||
local default gateway configured. This assigns a stable hostname to the local outbound IP addresses,
|
||||
useful for referencing them independently of the current network configuration state.</para></listitem>
|
||||
|
||||
<listitem><para>The mappings defined in <filename>/etc/hosts</filename> are resolved to their
|
||||
configured addresses and back, but they will not affect lookups for non-address types (like MX).
|
||||
Support for <filename>/etc/hosts</filename> may be disabled with <varname>ReadEtcHosts=no</varname>,
|
||||
|
||||
@ -360,16 +360,15 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
|
||||
return t - r;
|
||||
}
|
||||
|
||||
char* xescape_full(const char *s, const char *bad, size_t console_width, XEscapeFlags flags) {
|
||||
char* xescape_full(const char *s, const char *bad, size_t console_width, bool eight_bits) {
|
||||
char *ans, *t, *prev, *prev2;
|
||||
const char *f;
|
||||
|
||||
/* Escapes all chars in bad, in addition to \ and all special chars, in \xFF style escaping. May be
|
||||
* reversed with cunescape(). If XESCAPE_8_BIT is specified, characters >= 127 are let through
|
||||
* unchanged. This corresponds to non-ASCII printable characters in pre-unicode encodings.
|
||||
* reversed with cunescape(). If eight_bits is true, characters >= 127 are let through unchanged.
|
||||
* This corresponds to non-ASCII printable characters in pre-unicode encodings.
|
||||
*
|
||||
* If console_width is reached, or XESCAPE_FORCE_ELLIPSIS is set, output is truncated and "..." is
|
||||
* appended. */
|
||||
* If console_width is reached, output is truncated and "..." is appended. */
|
||||
|
||||
if (console_width == 0)
|
||||
return strdup("");
|
||||
@ -381,23 +380,17 @@ char* xescape_full(const char *s, const char *bad, size_t console_width, XEscape
|
||||
memset(ans, '_', MIN(strlen(s), console_width) * 4);
|
||||
ans[MIN(strlen(s), console_width) * 4] = 0;
|
||||
|
||||
bool force_ellipsis = FLAGS_SET(flags, XESCAPE_FORCE_ELLIPSIS);
|
||||
|
||||
for (f = s, t = prev = prev2 = ans; ; f++) {
|
||||
char *tmp_t = t;
|
||||
|
||||
if (!*f) {
|
||||
if (force_ellipsis)
|
||||
break;
|
||||
|
||||
*t = 0;
|
||||
return ans;
|
||||
}
|
||||
|
||||
if ((unsigned char) *f < ' ' ||
|
||||
(!FLAGS_SET(flags, XESCAPE_8_BIT) && (unsigned char) *f >= 127) ||
|
||||
if ((unsigned char) *f < ' ' || (!eight_bits && (unsigned char) *f >= 127) ||
|
||||
*f == '\\' || strchr(bad, *f)) {
|
||||
if ((size_t) (t - ans) + 4 + 3 * force_ellipsis > console_width)
|
||||
if ((size_t) (t - ans) + 4 > console_width)
|
||||
break;
|
||||
|
||||
*(t++) = '\\';
|
||||
@ -405,7 +398,7 @@ char* xescape_full(const char *s, const char *bad, size_t console_width, XEscape
|
||||
*(t++) = hexchar(*f >> 4);
|
||||
*(t++) = hexchar(*f);
|
||||
} else {
|
||||
if ((size_t) (t - ans) + 1 + 3 * force_ellipsis > console_width)
|
||||
if ((size_t) (t - ans) + 1 > console_width)
|
||||
break;
|
||||
|
||||
*(t++) = *f;
|
||||
@ -434,13 +427,11 @@ char* xescape_full(const char *s, const char *bad, size_t console_width, XEscape
|
||||
return ans;
|
||||
}
|
||||
|
||||
char* escape_non_printable_full(const char *str, size_t console_width, XEscapeFlags flags) {
|
||||
if (FLAGS_SET(flags, XESCAPE_8_BIT))
|
||||
return xescape_full(str, "", console_width, flags);
|
||||
char* escape_non_printable_full(const char *str, size_t console_width, bool eight_bit) {
|
||||
if (eight_bit)
|
||||
return xescape_full(str, "", console_width, true);
|
||||
else
|
||||
return utf8_escape_non_printable_full(str,
|
||||
console_width,
|
||||
FLAGS_SET(flags, XESCAPE_FORCE_ELLIPSIS));
|
||||
return utf8_escape_non_printable_full(str, console_width);
|
||||
}
|
||||
|
||||
char* octescape(const char *s, size_t len) {
|
||||
@ -471,15 +462,19 @@ char* octescape(const char *s, size_t len) {
|
||||
|
||||
}
|
||||
|
||||
static char* strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
|
||||
static char* strcpy_backslash_escaped(char *t, const char *s, const char *bad, bool escape_tab_nl) {
|
||||
assert(bad);
|
||||
|
||||
for (; *s; s++)
|
||||
if (char_is_cc(*s))
|
||||
t += cescape_char(*s, t);
|
||||
else {
|
||||
for (; *s; s++) {
|
||||
if (escape_tab_nl && IN_SET(*s, '\n', '\t')) {
|
||||
*(t++) = '\\';
|
||||
*(t++) = *s == '\n' ? 'n' : 't';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*s == '\\' || strchr(bad, *s))
|
||||
*(t++) = '\\';
|
||||
|
||||
*(t++) = *s;
|
||||
}
|
||||
|
||||
@ -487,58 +482,68 @@ static char* strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
|
||||
}
|
||||
|
||||
char* shell_escape(const char *s, const char *bad) {
|
||||
char *buf, *t;
|
||||
char *r, *t;
|
||||
|
||||
buf = new(char, strlen(s)*4+1);
|
||||
if (!buf)
|
||||
r = new(char, strlen(s)*2+1);
|
||||
if (!r)
|
||||
return NULL;
|
||||
|
||||
t = strcpy_backslash_escaped(buf, s, bad);
|
||||
t = strcpy_backslash_escaped(r, s, bad, false);
|
||||
*t = 0;
|
||||
|
||||
return buf;
|
||||
return r;
|
||||
}
|
||||
|
||||
char* shell_maybe_quote(const char *s, ShellEscapeFlags flags) {
|
||||
char* shell_maybe_quote(const char *s, EscapeStyle style) {
|
||||
const char *p;
|
||||
char *buf, *t;
|
||||
char *r, *t;
|
||||
|
||||
assert(s);
|
||||
|
||||
/* Encloses a string in quotes if necessary to make it OK as a shell string. */
|
||||
|
||||
if (FLAGS_SET(flags, SHELL_ESCAPE_EMPTY) && isempty(s))
|
||||
return strdup("\"\""); /* We don't use $'' here in the POSIX mode. "" is fine too. */
|
||||
/* Encloses a string in quotes if necessary to make it OK as a shell
|
||||
* string. Note that we treat benign UTF-8 characters as needing
|
||||
* escaping too, but that should be OK. */
|
||||
|
||||
for (p = s; *p; p++)
|
||||
if (char_is_cc(*p) ||
|
||||
strchr(WHITESPACE SHELL_NEED_QUOTES, *p))
|
||||
if (*p <= ' ' ||
|
||||
*p >= 127 ||
|
||||
strchr(SHELL_NEED_QUOTES, *p))
|
||||
break;
|
||||
|
||||
if (!*p)
|
||||
return strdup(s);
|
||||
|
||||
buf = new(char, FLAGS_SET(flags, SHELL_ESCAPE_POSIX) + 1 + strlen(s)*4 + 1 + 1);
|
||||
if (!buf)
|
||||
r = new(char, (style == ESCAPE_POSIX) + 1 + strlen(s)*2 + 1 + 1);
|
||||
if (!r)
|
||||
return NULL;
|
||||
|
||||
t = buf;
|
||||
if (FLAGS_SET(flags, SHELL_ESCAPE_POSIX)) {
|
||||
t = r;
|
||||
switch (style) {
|
||||
case ESCAPE_BACKSLASH:
|
||||
case ESCAPE_BACKSLASH_ONELINE:
|
||||
*(t++) = '"';
|
||||
break;
|
||||
case ESCAPE_POSIX:
|
||||
*(t++) = '$';
|
||||
*(t++) = '\'';
|
||||
} else
|
||||
*(t++) = '"';
|
||||
break;
|
||||
default:
|
||||
assert_not_reached("Bad EscapeStyle");
|
||||
}
|
||||
|
||||
t = mempcpy(t, s, p - s);
|
||||
|
||||
t = strcpy_backslash_escaped(t, p,
|
||||
FLAGS_SET(flags, SHELL_ESCAPE_POSIX) ? SHELL_NEED_ESCAPE_POSIX : SHELL_NEED_ESCAPE);
|
||||
|
||||
if (FLAGS_SET(flags, SHELL_ESCAPE_POSIX))
|
||||
*(t++) = '\'';
|
||||
if (IN_SET(style, ESCAPE_BACKSLASH, ESCAPE_BACKSLASH_ONELINE))
|
||||
t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE,
|
||||
style == ESCAPE_BACKSLASH_ONELINE);
|
||||
else
|
||||
t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE_POSIX, true);
|
||||
|
||||
if (IN_SET(style, ESCAPE_BACKSLASH, ESCAPE_BACKSLASH_ONELINE))
|
||||
*(t++) = '"';
|
||||
else
|
||||
*(t++) = '\'';
|
||||
*t = 0;
|
||||
|
||||
return str_realloc(buf);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -33,13 +33,15 @@ typedef enum UnescapeFlags {
|
||||
UNESCAPE_ACCEPT_NUL = 1 << 1,
|
||||
} UnescapeFlags;
|
||||
|
||||
typedef enum ShellEscapeFlags {
|
||||
/* The default is to add shell quotes ("") so the shell will consider this a single argument.
|
||||
* Tabs and newlines are escaped. */
|
||||
|
||||
SHELL_ESCAPE_POSIX = 1 << 1, /* Use POSIX shell escape syntax (a string enclosed in $'') instead of plain quotes. */
|
||||
SHELL_ESCAPE_EMPTY = 1 << 2, /* Format empty arguments as "". */
|
||||
} ShellEscapeFlags;
|
||||
typedef enum EscapeStyle {
|
||||
ESCAPE_BACKSLASH = 1, /* Add shell quotes ("") so the shell will consider this a single
|
||||
argument, possibly multiline. Tabs and newlines are not escaped. */
|
||||
ESCAPE_BACKSLASH_ONELINE = 2, /* Similar to ESCAPE_BACKSLASH, but always produces a single-line
|
||||
string instead. Shell escape sequences are produced for tabs and
|
||||
newlines. */
|
||||
ESCAPE_POSIX = 3, /* Similar to ESCAPE_BACKSLASH_ONELINE, but uses POSIX shell escape
|
||||
* syntax (a string enclosed in $'') instead of plain quotes. */
|
||||
} EscapeStyle;
|
||||
|
||||
char* cescape(const char *s);
|
||||
char* cescape_length(const char *s, size_t n);
|
||||
@ -54,17 +56,12 @@ static inline int cunescape(const char *s, UnescapeFlags flags, char **ret) {
|
||||
}
|
||||
int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit, bool accept_nul);
|
||||
|
||||
typedef enum XEscapeFlags {
|
||||
XESCAPE_8_BIT = 1 << 0,
|
||||
XESCAPE_FORCE_ELLIPSIS = 1 << 1,
|
||||
} XEscapeFlags;
|
||||
|
||||
char* xescape_full(const char *s, const char *bad, size_t console_width, XEscapeFlags flags);
|
||||
char* xescape_full(const char *s, const char *bad, size_t console_width, bool eight_bits);
|
||||
static inline char* xescape(const char *s, const char *bad) {
|
||||
return xescape_full(s, bad, SIZE_MAX, 0);
|
||||
return xescape_full(s, bad, SIZE_MAX, false);
|
||||
}
|
||||
char* octescape(const char *s, size_t len);
|
||||
char* escape_non_printable_full(const char *str, size_t console_width, XEscapeFlags flags);
|
||||
char* escape_non_printable_full(const char *str, size_t console_width, bool eight_bit);
|
||||
|
||||
char* shell_escape(const char *s, const char *bad);
|
||||
char* shell_maybe_quote(const char *s, ShellEscapeFlags flags);
|
||||
char* shell_maybe_quote(const char *s, EscapeStyle style);
|
||||
|
||||
@ -364,40 +364,32 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int read_virtual_file(const char *filename, size_t max_size, char **ret_contents, size_t *ret_size) {
|
||||
int read_full_virtual_file(const char *filename, char **ret_contents, size_t *ret_size) {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
struct stat st;
|
||||
size_t n, size;
|
||||
int n_retries;
|
||||
bool truncated = false;
|
||||
|
||||
assert(ret_contents);
|
||||
|
||||
/* Virtual filesystems such as sysfs or procfs use kernfs, and kernfs can work with two sorts of
|
||||
* virtual files. One sort uses "seq_file", and the results of the first read are buffered for the
|
||||
* second read. The other sort uses "raw" reads which always go direct to the device. In the latter
|
||||
* case, the content of the virtual file must be retrieved with a single read otherwise a second read
|
||||
* might get the new value instead of finding EOF immediately. That's the reason why the usage of
|
||||
* fread(3) is prohibited in this case as it always performs a second call to read(2) looking for
|
||||
* EOF. See issue #13585.
|
||||
*
|
||||
* max_size specifies a limit on the bytes read. If max_size is SIZE_MAX, the full file is read. If
|
||||
* the the full file is too large to read, an error is returned. For other values of max_size,
|
||||
* *partial contents* may be returned. (Though the read is still done using one syscall.)
|
||||
* Returns 0 on partial success, 1 if untruncated contents were read. */
|
||||
/* Virtual filesystems such as sysfs or procfs use kernfs, and kernfs can work
|
||||
* with two sorts of virtual files. One sort uses "seq_file", and the results of
|
||||
* the first read are buffered for the second read. The other sort uses "raw"
|
||||
* reads which always go direct to the device. In the latter case, the content of
|
||||
* the virtual file must be retrieved with a single read otherwise a second read
|
||||
* might get the new value instead of finding EOF immediately. That's the reason
|
||||
* why the usage of fread(3) is prohibited in this case as it always performs a
|
||||
* second call to read(2) looking for EOF. See issue 13585. */
|
||||
|
||||
fd = open(filename, O_RDONLY|O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
assert(max_size <= READ_FULL_BYTES_MAX || max_size == SIZE_MAX);
|
||||
|
||||
/* Limit the number of attempts to read the number of bytes returned by fstat(). */
|
||||
n_retries = 3;
|
||||
|
||||
for (;;) {
|
||||
struct stat st;
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
@ -407,16 +399,13 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents
|
||||
/* Be prepared for files from /proc which generally report a file size of 0. */
|
||||
assert_cc(READ_FULL_BYTES_MAX < SSIZE_MAX);
|
||||
if (st.st_size > 0) {
|
||||
if (st.st_size > SSIZE_MAX) /* Avoid overflow with 32-bit size_t and 64-bit off_t. */
|
||||
return -EFBIG;
|
||||
|
||||
size = MIN((size_t) st.st_size, max_size);
|
||||
if (size > READ_FULL_BYTES_MAX)
|
||||
if (st.st_size > READ_FULL_BYTES_MAX)
|
||||
return -EFBIG;
|
||||
|
||||
size = st.st_size;
|
||||
n_retries--;
|
||||
} else {
|
||||
size = MIN(READ_FULL_BYTES_MAX, max_size);
|
||||
size = READ_FULL_BYTES_MAX;
|
||||
n_retries = 0;
|
||||
}
|
||||
|
||||
@ -424,7 +413,7 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
/* Use a bigger allocation if we got it anyway, but not more than the limit. */
|
||||
size = MIN3(malloc_usable_size(buf) - 1, max_size, READ_FULL_BYTES_MAX);
|
||||
size = MIN(malloc_usable_size(buf) - 1, READ_FULL_BYTES_MAX);
|
||||
|
||||
for (;;) {
|
||||
ssize_t k;
|
||||
@ -451,16 +440,9 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents
|
||||
* processing, let's try again either with a bigger guessed size or the new
|
||||
* file size. */
|
||||
|
||||
if (n_retries <= 0) {
|
||||
if (max_size == SIZE_MAX)
|
||||
if (n_retries <= 0)
|
||||
return st.st_size > 0 ? -EIO : -EFBIG;
|
||||
|
||||
/* Accept a short read, but truncate it appropropriately. */
|
||||
n = MIN(n, max_size);
|
||||
truncated = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (lseek(fd, 0, SEEK_SET) < 0)
|
||||
return -errno;
|
||||
|
||||
@ -488,7 +470,7 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents
|
||||
buf[n] = 0;
|
||||
*ret_contents = TAKE_PTR(buf);
|
||||
|
||||
return !truncated;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_full_stream_full(
|
||||
@ -932,19 +914,12 @@ int xfopenat(int dir_fd, const char *path, const char *mode, int flags, FILE **r
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int search_and_fopen_internal(
|
||||
const char *path,
|
||||
const char *mode,
|
||||
const char *root,
|
||||
char **search,
|
||||
FILE **ret,
|
||||
char **ret_path) {
|
||||
|
||||
static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) {
|
||||
char **i;
|
||||
|
||||
assert(path);
|
||||
assert(mode);
|
||||
assert(ret);
|
||||
assert(_f);
|
||||
|
||||
if (!path_strv_resolve_uniq(search, root))
|
||||
return -ENOMEM;
|
||||
@ -959,10 +934,7 @@ static int search_and_fopen_internal(
|
||||
|
||||
f = fopen(p, mode);
|
||||
if (f) {
|
||||
if (ret_path)
|
||||
*ret_path = path_simplify(TAKE_PTR(p), true);
|
||||
|
||||
*ret = f;
|
||||
*_f = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -973,84 +945,52 @@ static int search_and_fopen_internal(
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int search_and_fopen(
|
||||
const char *filename,
|
||||
const char *mode,
|
||||
const char *root,
|
||||
const char **search,
|
||||
FILE **ret,
|
||||
char **ret_path) {
|
||||
|
||||
int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) {
|
||||
_cleanup_strv_free_ char **copy = NULL;
|
||||
|
||||
assert(filename);
|
||||
assert(path);
|
||||
assert(mode);
|
||||
assert(ret);
|
||||
assert(_f);
|
||||
|
||||
if (path_is_absolute(filename)) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
if (path_is_absolute(path)) {
|
||||
FILE *f;
|
||||
|
||||
f = fopen(filename, mode);
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
if (ret_path) {
|
||||
char *p;
|
||||
|
||||
p = strdup(filename);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret_path = path_simplify(p, true);
|
||||
f = fopen(path, mode);
|
||||
if (f) {
|
||||
*_f = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(f);
|
||||
return 0;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
copy = strv_copy((char**) search);
|
||||
if (!copy)
|
||||
return -ENOMEM;
|
||||
|
||||
return search_and_fopen_internal(filename, mode, root, copy, ret, ret_path);
|
||||
return search_and_fopen_internal(path, mode, root, copy, _f);
|
||||
}
|
||||
|
||||
int search_and_fopen_nulstr(
|
||||
const char *filename,
|
||||
const char *mode,
|
||||
const char *root,
|
||||
const char *search,
|
||||
FILE **ret,
|
||||
char **ret_path) {
|
||||
|
||||
int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) {
|
||||
_cleanup_strv_free_ char **s = NULL;
|
||||
|
||||
if (path_is_absolute(filename)) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
if (path_is_absolute(path)) {
|
||||
FILE *f;
|
||||
|
||||
f = fopen(filename, mode);
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
if (ret_path) {
|
||||
char *p;
|
||||
|
||||
p = strdup(filename);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret_path = path_simplify(p, true);
|
||||
f = fopen(path, mode);
|
||||
if (f) {
|
||||
*_f = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(f);
|
||||
return 0;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
s = strv_split_nulstr(search);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
return search_and_fopen_internal(filename, mode, root, s, ret, ret_path);
|
||||
return search_and_fopen_internal(path, mode, root, s, _f);
|
||||
}
|
||||
|
||||
int chase_symlinks_and_fopen_unlocked(
|
||||
|
||||
@ -65,12 +65,7 @@ int read_full_file_full(int dir_fd, const char *filename, uint64_t offset, size_
|
||||
static inline int read_full_file(const char *filename, char **ret_contents, size_t *ret_size) {
|
||||
return read_full_file_full(AT_FDCWD, filename, UINT64_MAX, SIZE_MAX, 0, NULL, ret_contents, ret_size);
|
||||
}
|
||||
|
||||
int read_virtual_file(const char *filename, size_t max_size, char **ret_contents, size_t *ret_size);
|
||||
static inline int read_full_virtual_file(const char *filename, char **ret_contents, size_t *ret_size) {
|
||||
return read_virtual_file(filename, SIZE_MAX, ret_contents, ret_size);
|
||||
}
|
||||
|
||||
int read_full_virtual_file(const char *filename, char **ret_contents, size_t *ret_size);
|
||||
int read_full_stream_full(FILE *f, const char *filename, uint64_t offset, size_t size, ReadFullFileFlags flags, char **ret_contents, size_t *ret_size);
|
||||
static inline int read_full_stream(FILE *f, char **ret_contents, size_t *ret_size) {
|
||||
return read_full_stream_full(f, NULL, UINT64_MAX, SIZE_MAX, 0, ret_contents, ret_size);
|
||||
@ -85,8 +80,8 @@ int get_proc_field(const char *filename, const char *pattern, const char *termin
|
||||
DIR *xopendirat(int dirfd, const char *name, int flags);
|
||||
int xfopenat(int dir_fd, const char *path, const char *mode, int flags, FILE **ret);
|
||||
|
||||
int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **ret, char **ret_path);
|
||||
int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **ret, char **ret_path);
|
||||
int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f);
|
||||
int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f);
|
||||
|
||||
int chase_symlinks_and_fopen_unlocked(
|
||||
const char *path,
|
||||
|
||||
@ -28,8 +28,3 @@ static inline bool is_gateway_hostname(const char *hostname) {
|
||||
/* This tries to identify the valid syntaxes for the our synthetic "gateway" host. */
|
||||
return STRCASE_IN_SET(hostname, "_gateway", "_gateway.");
|
||||
}
|
||||
|
||||
static inline bool is_outbound_hostname(const char *hostname) {
|
||||
/* This tries to identify the valid syntaxes for the our synthetic "outbound" host. */
|
||||
return STRCASE_IN_SET(hostname, "_outbound", "_outbound.");
|
||||
}
|
||||
|
||||
@ -123,136 +123,64 @@ int get_process_comm(pid_t pid, char **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_process_cmdline_nulstr(
|
||||
pid_t pid,
|
||||
size_t max_size,
|
||||
ProcessCmdlineFlags flags,
|
||||
char **ret,
|
||||
size_t *ret_size) {
|
||||
|
||||
int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **line) {
|
||||
_cleanup_free_ char *t = NULL, *ans = NULL;
|
||||
const char *p;
|
||||
char *t;
|
||||
size_t k;
|
||||
int r;
|
||||
|
||||
/* Retrieves a process' command line as a "sized nulstr", i.e. possibly without the last NUL, but
|
||||
* with a specified size.
|
||||
assert(line);
|
||||
assert(pid >= 0);
|
||||
|
||||
/* Retrieves a process' command line. Replaces non-utf8 bytes by replacement character (<28>). If
|
||||
* max_columns is != -1 will return a string of the specified console width at most, abbreviated with
|
||||
* an ellipsis. If PROCESS_CMDLINE_COMM_FALLBACK is specified in flags and the process has no command
|
||||
* line set (the case for kernel threads), or has a command line that resolves to the empty string
|
||||
* will return the "comm" name of the process instead. This will use at most _SC_ARG_MAX bytes of
|
||||
* input data.
|
||||
*
|
||||
* If PROCESS_CMDLINE_COMM_FALLBACK is specified in flags and the process has no command line set
|
||||
* (the case for kernel threads), or has a command line that resolves to the empty string, will
|
||||
* return the "comm" name of the process instead. This will use at most _SC_ARG_MAX bytes of input
|
||||
* data.
|
||||
*
|
||||
* Returns an error, 0 if output was read but is truncated, 1 otherwise.
|
||||
*/
|
||||
* Returns -ESRCH if the process doesn't exist, and -ENOENT if the process has no command line (and
|
||||
* comm_fallback is false). Returns 0 and sets *line otherwise. */
|
||||
|
||||
p = procfs_file_alloca(pid, "cmdline");
|
||||
r = read_virtual_file(p, max_size, &t, &k); /* Let's assume that each input byte results in >= 1
|
||||
* columns of output. We ignore zero-width codepoints. */
|
||||
r = read_full_virtual_file(p, &t, &k);
|
||||
if (r == -ENOENT)
|
||||
return -ESRCH;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (k == 0) {
|
||||
t = mfree(t);
|
||||
|
||||
if (!(flags & PROCESS_CMDLINE_COMM_FALLBACK))
|
||||
return -ENOENT;
|
||||
|
||||
/* Kernel threads have no argv[] */
|
||||
_cleanup_free_ char *comm = NULL;
|
||||
|
||||
r = get_process_comm(pid, &comm);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
t = strjoin("[", comm, "]");
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
|
||||
k = strlen(t);
|
||||
r = k <= max_size;
|
||||
if (r == 0) /* truncation */
|
||||
t[max_size] = '\0';
|
||||
}
|
||||
|
||||
*ret = t;
|
||||
*ret_size = k;
|
||||
return r;
|
||||
}
|
||||
|
||||
int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **line) {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
size_t k;
|
||||
char *ans;
|
||||
|
||||
assert(line);
|
||||
assert(pid >= 0);
|
||||
|
||||
/* Retrieve adn format a commandline. See above for discussion of retrieval options.
|
||||
*
|
||||
* There are two main formatting modes:
|
||||
*
|
||||
* - when PROCESS_CMDLINE_QUOTE is specified, output is quoted in C/Python style. If no shell special
|
||||
* characters are present, this output can be copy-pasted into the terminal to execute. UTF-8
|
||||
* output is assumed.
|
||||
*
|
||||
* - otherwise, a compact non-roundtrippable form is returned. Non-UTF8 bytes are replaced by <EFBFBD>. The
|
||||
* returned string is of the specified console width at most, abbreviated with an ellipsis.
|
||||
*
|
||||
* Returns -ESRCH if the process doesn't exist, and -ENOENT if the process has no command line (and
|
||||
* PROCESS_CMDLINE_COMM_FALLBACK is not specified). Returns 0 and sets *line otherwise. */
|
||||
|
||||
int full = get_process_cmdline_nulstr(pid, max_columns, flags, &t, &k);
|
||||
if (full < 0)
|
||||
return full;
|
||||
|
||||
if (flags & (PROCESS_CMDLINE_QUOTE | PROCESS_CMDLINE_QUOTE_POSIX)) {
|
||||
ShellEscapeFlags shflags = SHELL_ESCAPE_EMPTY |
|
||||
FLAGS_SET(flags, PROCESS_CMDLINE_QUOTE_POSIX) * SHELL_ESCAPE_POSIX;
|
||||
|
||||
assert(!(flags & PROCESS_CMDLINE_USE_LOCALE));
|
||||
|
||||
_cleanup_strv_free_ char **args = NULL;
|
||||
|
||||
args = strv_parse_nulstr(t, k);
|
||||
if (!args)
|
||||
return -ENOMEM;
|
||||
|
||||
for (size_t i = 0; args[i]; i++) {
|
||||
char *e;
|
||||
|
||||
e = shell_maybe_quote(args[i], shflags);
|
||||
if (!e)
|
||||
return -ENOMEM;
|
||||
|
||||
free_and_replace(args[i], e);
|
||||
}
|
||||
|
||||
ans = strv_join(args, " ");
|
||||
if (!ans)
|
||||
return -ENOMEM;
|
||||
|
||||
} else {
|
||||
if (k > 0) {
|
||||
/* Arguments are separated by NULs. Let's replace those with spaces. */
|
||||
for (size_t i = 0; i < k - 1; i++)
|
||||
if (t[i] == '\0')
|
||||
t[i] = ' ';
|
||||
} else {
|
||||
if (!(flags & PROCESS_CMDLINE_COMM_FALLBACK))
|
||||
return -ENOENT;
|
||||
|
||||
/* Kernel threads have no argv[] */
|
||||
_cleanup_free_ char *t2 = NULL;
|
||||
|
||||
r = get_process_comm(pid, &t2);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
free(t);
|
||||
t = strjoin("[", t2, "]");
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
delete_trailing_chars(t, WHITESPACE);
|
||||
|
||||
bool eight_bit = (flags & PROCESS_CMDLINE_USE_LOCALE) && !is_locale_utf8();
|
||||
|
||||
ans = escape_non_printable_full(t, max_columns,
|
||||
eight_bit * XESCAPE_8_BIT | !full * XESCAPE_FORCE_ELLIPSIS);
|
||||
ans = escape_non_printable_full(t, max_columns, eight_bit);
|
||||
if (!ans)
|
||||
return -ENOMEM;
|
||||
|
||||
ans = str_realloc(ans);
|
||||
}
|
||||
|
||||
*line = ans;
|
||||
(void) str_realloc(&ans);
|
||||
*line = TAKE_PTR(ans);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -35,8 +35,6 @@
|
||||
typedef enum ProcessCmdlineFlags {
|
||||
PROCESS_CMDLINE_COMM_FALLBACK = 1 << 0,
|
||||
PROCESS_CMDLINE_USE_LOCALE = 1 << 1,
|
||||
PROCESS_CMDLINE_QUOTE = 1 << 2,
|
||||
PROCESS_CMDLINE_QUOTE_POSIX = 1 << 3,
|
||||
} ProcessCmdlineFlags;
|
||||
|
||||
int get_process_comm(pid_t pid, char **name);
|
||||
|
||||
@ -150,7 +150,7 @@ char *delete_chars(char *s, const char *bad) {
|
||||
}
|
||||
|
||||
char *delete_trailing_chars(char *s, const char *bad) {
|
||||
char *c = s;
|
||||
char *p, *c = s;
|
||||
|
||||
/* Drops all specified bad characters, at the end of the string */
|
||||
|
||||
@ -160,7 +160,7 @@ char *delete_trailing_chars(char *s, const char *bad) {
|
||||
if (!bad)
|
||||
bad = WHITESPACE;
|
||||
|
||||
for (char *p = s; *p; p++)
|
||||
for (p = s; *p; p++)
|
||||
if (!strchr(bad, *p))
|
||||
c = p + 1;
|
||||
|
||||
@ -193,28 +193,34 @@ char ascii_toupper(char x) {
|
||||
}
|
||||
|
||||
char *ascii_strlower(char *t) {
|
||||
char *p;
|
||||
|
||||
assert(t);
|
||||
|
||||
for (char *p = t; *p; p++)
|
||||
for (p = t; *p; p++)
|
||||
*p = ascii_tolower(*p);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
char *ascii_strupper(char *t) {
|
||||
char *p;
|
||||
|
||||
assert(t);
|
||||
|
||||
for (char *p = t; *p; p++)
|
||||
for (p = t; *p; p++)
|
||||
*p = ascii_toupper(*p);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
char *ascii_strlower_n(char *t, size_t n) {
|
||||
size_t i;
|
||||
|
||||
if (n <= 0)
|
||||
return t;
|
||||
|
||||
for (size_t i = 0; i < n; i++)
|
||||
for (i = 0; i < n; i++)
|
||||
t[i] = ascii_tolower(t[i]);
|
||||
|
||||
return t;
|
||||
@ -246,8 +252,10 @@ int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m) {
|
||||
}
|
||||
|
||||
bool chars_intersect(const char *a, const char *b) {
|
||||
const char *p;
|
||||
|
||||
/* Returns true if any of the chars in a are in b. */
|
||||
for (const char *p = a; *p; p++)
|
||||
for (p = a; *p; p++)
|
||||
if (strchr(b, *p))
|
||||
return true;
|
||||
|
||||
@ -255,6 +263,8 @@ bool chars_intersect(const char *a, const char *b) {
|
||||
}
|
||||
|
||||
bool string_has_cc(const char *p, const char *ok) {
|
||||
const char *t;
|
||||
|
||||
assert(p);
|
||||
|
||||
/*
|
||||
@ -263,11 +273,14 @@ bool string_has_cc(const char *p, const char *ok) {
|
||||
* considered OK.
|
||||
*/
|
||||
|
||||
for (const char *t = p; *t; t++) {
|
||||
for (t = p; *t; t++) {
|
||||
if (ok && strchr(ok, *t))
|
||||
continue;
|
||||
|
||||
if (char_is_cc(*t))
|
||||
if (*t > 0 && *t < ' ')
|
||||
return true;
|
||||
|
||||
if (*t == 127)
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -455,7 +468,7 @@ char *cellescape(char *buf, size_t len, const char *s) {
|
||||
* very end.
|
||||
*/
|
||||
|
||||
size_t i = 0, last_char_width[4] = {}, k = 0;
|
||||
size_t i = 0, last_char_width[4] = {}, k = 0, j;
|
||||
|
||||
assert(len > 0); /* at least a terminating NUL */
|
||||
|
||||
@ -484,7 +497,7 @@ char *cellescape(char *buf, size_t len, const char *s) {
|
||||
|
||||
/* Ellipsation is necessary. This means we might need to truncate the string again to make space for 4
|
||||
* characters ideally, but the buffer is shorter than that in the first place take what we can get */
|
||||
for (size_t j = 0; j < ELEMENTSOF(last_char_width); j++) {
|
||||
for (j = 0; j < ELEMENTSOF(last_char_width); j++) {
|
||||
|
||||
if (i + 4 <= len) /* nice, we reached our space goal */
|
||||
break;
|
||||
@ -971,12 +984,14 @@ int free_and_strndup(char **p, const char *s, size_t l) {
|
||||
}
|
||||
|
||||
bool string_is_safe(const char *p) {
|
||||
const char *t;
|
||||
|
||||
if (!p)
|
||||
return false;
|
||||
|
||||
/* Checks if the specified string contains no quotes or control characters */
|
||||
|
||||
for (const char *t = p; *t; t++) {
|
||||
for (t = p; *t; t++) {
|
||||
if (*t > 0 && *t < ' ') /* no control characters */
|
||||
return false;
|
||||
|
||||
|
||||
@ -129,9 +129,6 @@ static inline bool _pure_ in_charset(const char *s, const char* charset) {
|
||||
return s[strspn(s, charset)] == '\0';
|
||||
}
|
||||
|
||||
static inline bool char_is_cc(char p) {
|
||||
return (p >= 0 && p < ' ') || p == 127;
|
||||
}
|
||||
bool string_has_cc(const char *p, const char *ok) _pure_;
|
||||
|
||||
char *ellipsize_mem(const char *s, size_t old_length_bytes, size_t new_length_columns, unsigned percent);
|
||||
@ -219,13 +216,17 @@ static inline void *memory_startswith_no_case(const void *p, size_t sz, const ch
|
||||
return (uint8_t*) p + n;
|
||||
}
|
||||
|
||||
static inline char* str_realloc(char *p) {
|
||||
/* Reallocate *p to actual size. Ignore failure, and return the original string on error. */
|
||||
static inline char* str_realloc(char **p) {
|
||||
/* Reallocate *p to actual size */
|
||||
|
||||
if (!p)
|
||||
if (!*p)
|
||||
return NULL;
|
||||
|
||||
return realloc(p, strlen(p) + 1) ?: p;
|
||||
char *t = realloc(*p, strlen(*p) + 1);
|
||||
if (!t)
|
||||
return NULL;
|
||||
|
||||
return (*p = t);
|
||||
}
|
||||
|
||||
char* string_erase(char *x);
|
||||
|
||||
@ -196,7 +196,8 @@ char *utf8_escape_invalid(const char *str) {
|
||||
}
|
||||
|
||||
*s = '\0';
|
||||
return str_realloc(p);
|
||||
(void) str_realloc(&p);
|
||||
return p;
|
||||
}
|
||||
|
||||
static int utf8_char_console_width(const char *str) {
|
||||
@ -212,7 +213,7 @@ static int utf8_char_console_width(const char *str) {
|
||||
return unichar_iswide(c) ? 2 : 1;
|
||||
}
|
||||
|
||||
char *utf8_escape_non_printable_full(const char *str, size_t console_width, bool force_ellipsis) {
|
||||
char *utf8_escape_non_printable_full(const char *str, size_t console_width) {
|
||||
char *p, *s, *prev_s;
|
||||
size_t n = 0; /* estimated print width */
|
||||
|
||||
@ -229,12 +230,8 @@ char *utf8_escape_non_printable_full(const char *str, size_t console_width, bool
|
||||
int len;
|
||||
char *saved_s = s;
|
||||
|
||||
if (!*str) { /* done! */
|
||||
if (force_ellipsis)
|
||||
goto truncation;
|
||||
else
|
||||
if (!*str) /* done! */
|
||||
goto finish;
|
||||
}
|
||||
|
||||
len = utf8_encoded_valid_unichar(str, SIZE_MAX);
|
||||
if (len > 0) {
|
||||
@ -278,14 +275,15 @@ char *utf8_escape_non_printable_full(const char *str, size_t console_width, bool
|
||||
|
||||
truncation:
|
||||
/* Try to go back one if we don't have enough space for the ellipsis */
|
||||
if (n + 1 > console_width)
|
||||
if (n + 1 >= console_width)
|
||||
s = prev_s;
|
||||
|
||||
s = mempcpy(s, "…", strlen("…"));
|
||||
|
||||
finish:
|
||||
*s = '\0';
|
||||
return str_realloc(p);
|
||||
(void) str_realloc(&p);
|
||||
return p;
|
||||
}
|
||||
|
||||
char *ascii_is_valid(const char *str) {
|
||||
|
||||
@ -25,9 +25,9 @@ bool utf8_is_printable_newline(const char* str, size_t length, bool allow_newlin
|
||||
#define utf8_is_printable(str, length) utf8_is_printable_newline(str, length, true)
|
||||
|
||||
char *utf8_escape_invalid(const char *s);
|
||||
char *utf8_escape_non_printable_full(const char *str, size_t console_width, bool force_ellipsis);
|
||||
char *utf8_escape_non_printable_full(const char *str, size_t console_width);
|
||||
static inline char *utf8_escape_non_printable(const char *str) {
|
||||
return utf8_escape_non_printable_full(str, SIZE_MAX, false);
|
||||
return utf8_escape_non_printable_full(str, SIZE_MAX);
|
||||
}
|
||||
|
||||
size_t utf8_encode_unichar(char *out_utf8, char32_t g);
|
||||
|
||||
@ -65,12 +65,11 @@ static int apply_rule(const char *rule) {
|
||||
|
||||
static int apply_file(const char *path, bool ignore_enoent) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_free_ char *pp = NULL;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
|
||||
r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("binfmt.d"), &f, &pp);
|
||||
r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("binfmt.d"), &f);
|
||||
if (r < 0) {
|
||||
if (ignore_enoent && r == -ENOENT)
|
||||
return 0;
|
||||
@ -78,7 +77,7 @@ static int apply_file(const char *path, bool ignore_enoent) {
|
||||
return log_error_errno(r, "Failed to open file '%s': %m", path);
|
||||
}
|
||||
|
||||
log_debug("apply: %s", pp);
|
||||
log_debug("apply: %s", path);
|
||||
for (;;) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
char *p;
|
||||
@ -86,7 +85,7 @@ static int apply_file(const char *path, bool ignore_enoent) {
|
||||
|
||||
k = read_line(f, LONG_LINE_MAX, &line);
|
||||
if (k < 0)
|
||||
return log_error_errno(k, "Failed to read file '%s': %m", pp);
|
||||
return log_error_errno(k, "Failed to read file '%s': %m", path);
|
||||
if (k == 0)
|
||||
break;
|
||||
|
||||
|
||||
@ -1229,9 +1229,7 @@ static int append_process(sd_bus_message *reply, const char *p, pid_t pid, Set *
|
||||
p = buf;
|
||||
}
|
||||
|
||||
(void) get_process_cmdline(pid, SIZE_MAX,
|
||||
PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE,
|
||||
&cmdline);
|
||||
(void) get_process_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &cmdline);
|
||||
|
||||
return sd_bus_message_append(reply,
|
||||
"(sus)",
|
||||
|
||||
@ -848,7 +848,7 @@ static void job_print_done_status_message(Unit *u, JobType t, JobResult result)
|
||||
if (t == JOB_START && result == JOB_FAILED) {
|
||||
_cleanup_free_ char *quoted = NULL;
|
||||
|
||||
quoted = shell_maybe_quote(u->id, 0);
|
||||
quoted = shell_maybe_quote(u->id, ESCAPE_BACKSLASH);
|
||||
manager_status_printf(u->manager, STATUS_TYPE_NORMAL, NULL, "See 'systemctl status %s' for details.", strna(quoted));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1818,8 +1818,7 @@ int setup_namespace(
|
||||
DISSECT_IMAGE_DISCARD_ON_LOOP |
|
||||
DISSECT_IMAGE_RELAX_VAR_CHECK |
|
||||
DISSECT_IMAGE_FSCK |
|
||||
DISSECT_IMAGE_USR_NO_ROOT |
|
||||
DISSECT_IMAGE_GROWFS;
|
||||
DISSECT_IMAGE_USR_NO_ROOT;
|
||||
size_t n_mounts;
|
||||
int r;
|
||||
|
||||
|
||||
@ -665,7 +665,7 @@ static int get_process_container_parent_cmdline(pid_t pid, char** cmdline) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = get_process_cmdline(container_pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, cmdline);
|
||||
r = get_process_cmdline(container_pid, SIZE_MAX, 0, cmdline);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1145,7 +1145,7 @@ static int gather_pid_metadata(struct iovec_wrapper *iovw, Context *context) {
|
||||
if (sd_pid_get_slice(pid, &t) >= 0)
|
||||
(void) iovw_put_string_field_free(iovw, "COREDUMP_SLICE=", t);
|
||||
|
||||
if (get_process_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &t) >= 0)
|
||||
if (get_process_cmdline(pid, SIZE_MAX, 0, &t) >= 0)
|
||||
(void) iovw_put_string_field_free(iovw, "COREDUMP_CMDLINE=", t);
|
||||
|
||||
if (cg_pid_get_path_shifted(pid, NULL, &t) >= 0)
|
||||
|
||||
@ -49,8 +49,7 @@ static DissectImageFlags arg_flags =
|
||||
DISSECT_IMAGE_DISCARD_ON_LOOP |
|
||||
DISSECT_IMAGE_RELAX_VAR_CHECK |
|
||||
DISSECT_IMAGE_FSCK |
|
||||
DISSECT_IMAGE_USR_NO_ROOT |
|
||||
DISSECT_IMAGE_GROWFS;
|
||||
DISSECT_IMAGE_USR_NO_ROOT;
|
||||
static VeritySettings arg_verity_settings = VERITY_SETTINGS_DEFAULT;
|
||||
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
|
||||
static PagerFlags arg_pager_flags = 0;
|
||||
@ -76,7 +75,6 @@ static int help(void) {
|
||||
" --no-legend Do not show the headers and footers\n"
|
||||
" -r --read-only Mount read-only\n"
|
||||
" --fsck=BOOL Run fsck before mounting\n"
|
||||
" --growfs=BOOL Grow file system to partition size, if marked\n"
|
||||
" --mkdir Make mount directory before mounting, if missing\n"
|
||||
" --discard=MODE Choose 'discard' mode (disabled, loop, all, crypto)\n"
|
||||
" --root-hash=HASH Specify root hash for verity\n"
|
||||
@ -114,7 +112,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_NO_LEGEND,
|
||||
ARG_DISCARD,
|
||||
ARG_FSCK,
|
||||
ARG_GROWFS,
|
||||
ARG_ROOT_HASH,
|
||||
ARG_ROOT_HASH_SIG,
|
||||
ARG_VERITY_DATA,
|
||||
@ -131,7 +128,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "read-only", no_argument, NULL, 'r' },
|
||||
{ "discard", required_argument, NULL, ARG_DISCARD },
|
||||
{ "fsck", required_argument, NULL, ARG_FSCK },
|
||||
{ "growfs", required_argument, NULL, ARG_GROWFS },
|
||||
{ "root-hash", required_argument, NULL, ARG_ROOT_HASH },
|
||||
{ "root-hash-sig", required_argument, NULL, ARG_ROOT_HASH_SIG },
|
||||
{ "verity-data", required_argument, NULL, ARG_VERITY_DATA },
|
||||
@ -268,14 +264,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
SET_FLAG(arg_flags, DISSECT_IMAGE_FSCK, r);
|
||||
break;
|
||||
|
||||
case ARG_GROWFS:
|
||||
r = parse_boolean(optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse --growfs= parameter: %s", optarg);
|
||||
|
||||
SET_FLAG(arg_flags, DISSECT_IMAGE_GROWFS, r);
|
||||
break;
|
||||
|
||||
case ARG_JSON:
|
||||
r = parse_json_argument(optarg, &arg_json_format_flags);
|
||||
if (r <= 0)
|
||||
@ -479,7 +467,7 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) {
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
t = table_new("rw", "designator", "partition uuid", "partition label", "fstype", "architecture", "verity", "growfs", "node", "partno");
|
||||
t = table_new("rw", "designator", "partition uuid", "partition label", "fstype", "architecture", "verity", "node", "partno");
|
||||
if (!t)
|
||||
return log_oom();
|
||||
|
||||
@ -523,10 +511,6 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) {
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
r = table_add_many(t, TABLE_BOOLEAN, (int) p->growfs);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
if (p->partno < 0) /* no partition table, naked file system */ {
|
||||
r = table_add_cell(t, NULL, TABLE_STRING, arg_image);
|
||||
if (r < 0)
|
||||
|
||||
@ -70,7 +70,7 @@ static int load_and_print(void) {
|
||||
t = strchr(*i, '=');
|
||||
assert(t);
|
||||
|
||||
q = shell_maybe_quote(t + 1, 0);
|
||||
q = shell_maybe_quote(t + 1, ESCAPE_BACKSLASH);
|
||||
if (!q)
|
||||
return log_oom();
|
||||
|
||||
|
||||
@ -1357,8 +1357,7 @@ static int run(int argc, char *argv[]) {
|
||||
DISSECT_IMAGE_REQUIRE_ROOT |
|
||||
DISSECT_IMAGE_VALIDATE_OS |
|
||||
DISSECT_IMAGE_RELAX_VAR_CHECK |
|
||||
DISSECT_IMAGE_FSCK |
|
||||
DISSECT_IMAGE_GROWFS,
|
||||
DISSECT_IMAGE_FSCK,
|
||||
&unlink_dir,
|
||||
&loop_device,
|
||||
&decrypted_image);
|
||||
|
||||
@ -194,7 +194,6 @@ static int add_mount(
|
||||
const char *where,
|
||||
const char *fstype,
|
||||
bool rw,
|
||||
bool growfs,
|
||||
const char *options,
|
||||
const char *description,
|
||||
const char *post) {
|
||||
@ -272,18 +271,8 @@ static int add_mount(
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write unit file %s: %m", p);
|
||||
|
||||
if (growfs) {
|
||||
r = generator_hook_up_growfs(arg_dest, where, post);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (post) {
|
||||
r = generator_add_symlink(arg_dest, post, "requires", unit);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (post)
|
||||
return generator_add_symlink(arg_dest, post, "requires", unit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -332,7 +321,6 @@ static int add_partition_mount(
|
||||
where,
|
||||
p->fstype,
|
||||
p->rw,
|
||||
p->growfs,
|
||||
NULL,
|
||||
description,
|
||||
SPECIAL_LOCAL_FS_TARGET);
|
||||
@ -397,7 +385,6 @@ static int add_automount(
|
||||
const char *where,
|
||||
const char *fstype,
|
||||
bool rw,
|
||||
bool growfs,
|
||||
const char *options,
|
||||
const char *description,
|
||||
usec_t timeout) {
|
||||
@ -419,7 +406,6 @@ static int add_automount(
|
||||
where,
|
||||
fstype,
|
||||
rw,
|
||||
growfs,
|
||||
opt,
|
||||
description,
|
||||
NULL);
|
||||
@ -495,8 +481,7 @@ static int add_xbootldr(DissectedPartition *p) {
|
||||
p->node,
|
||||
"/boot",
|
||||
p->fstype,
|
||||
/* rw= */ true,
|
||||
/* growfs= */ false,
|
||||
true,
|
||||
esp_or_xbootldr_options(p),
|
||||
"Boot Loader Partition",
|
||||
120 * USEC_PER_SEC);
|
||||
@ -570,8 +555,7 @@ static int add_esp(DissectedPartition *p, bool has_xbootldr) {
|
||||
p->node,
|
||||
esp_path,
|
||||
p->fstype,
|
||||
/* rw= */ true,
|
||||
/* growfs= */ false,
|
||||
true,
|
||||
esp_or_xbootldr_options(p),
|
||||
"EFI System Partition Automount",
|
||||
120 * USEC_PER_SEC);
|
||||
@ -667,8 +651,7 @@ static int add_root_mount(void) {
|
||||
"/dev/gpt-auto-root",
|
||||
in_initrd() ? "/sysroot" : "/",
|
||||
NULL,
|
||||
/* rw= */ arg_root_rw > 0,
|
||||
/* growfs= */ false,
|
||||
arg_root_rw > 0,
|
||||
NULL,
|
||||
"Root Partition",
|
||||
in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET);
|
||||
|
||||
@ -1327,7 +1327,7 @@ static int manager_load_key_pair(Manager *m) {
|
||||
m->private_key = NULL;
|
||||
}
|
||||
|
||||
r = search_and_fopen_nulstr("local.private", "re", NULL, KEY_PATHS_NULSTR, &f, NULL);
|
||||
r = search_and_fopen_nulstr("local.private", "re", NULL, KEY_PATHS_NULSTR, &f);
|
||||
if (r == -ENOENT)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
|
||||
@ -2154,7 +2154,7 @@ int main(int argc, char *argv[]) {
|
||||
DISSECT_IMAGE_REQUIRE_ROOT |
|
||||
DISSECT_IMAGE_VALIDATE_OS |
|
||||
DISSECT_IMAGE_RELAX_VAR_CHECK |
|
||||
(arg_action == ACTION_UPDATE_CATALOG ? DISSECT_IMAGE_FSCK|DISSECT_IMAGE_GROWFS : DISSECT_IMAGE_READ_ONLY),
|
||||
(arg_action == ACTION_UPDATE_CATALOG ? DISSECT_IMAGE_FSCK : DISSECT_IMAGE_READ_ONLY),
|
||||
&unlink_dir,
|
||||
&loop_device,
|
||||
&decrypted_image);
|
||||
|
||||
@ -225,7 +225,7 @@ static void client_context_read_basic(ClientContext *c) {
|
||||
if (get_process_exe(c->pid, &t) >= 0)
|
||||
free_and_replace(c->exe, t);
|
||||
|
||||
if (get_process_cmdline(c->pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &t) >= 0)
|
||||
if (get_process_cmdline(c->pid, SIZE_MAX, 0, &t) >= 0)
|
||||
free_and_replace(c->cmdline, t);
|
||||
|
||||
if (get_process_capeff(c->pid, &t) >= 0)
|
||||
|
||||
@ -146,8 +146,7 @@ static int run(int argc, char *argv[]) {
|
||||
DISSECT_IMAGE_REQUIRE_ROOT |
|
||||
DISSECT_IMAGE_VALIDATE_OS |
|
||||
DISSECT_IMAGE_RELAX_VAR_CHECK |
|
||||
DISSECT_IMAGE_FSCK |
|
||||
DISSECT_IMAGE_GROWFS,
|
||||
DISSECT_IMAGE_FSCK,
|
||||
&unlink_dir,
|
||||
&loop_device,
|
||||
&decrypted_image);
|
||||
|
||||
@ -62,13 +62,12 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
||||
|
||||
static int apply_file(struct kmod_ctx *ctx, const char *path, bool ignore_enoent) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_free_ char *pp = NULL;
|
||||
int r;
|
||||
|
||||
assert(ctx);
|
||||
assert(path);
|
||||
|
||||
r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f, &pp);
|
||||
r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f);
|
||||
if (r < 0) {
|
||||
if (ignore_enoent && r == -ENOENT)
|
||||
return 0;
|
||||
@ -76,7 +75,7 @@ static int apply_file(struct kmod_ctx *ctx, const char *path, bool ignore_enoent
|
||||
return log_error_errno(r, "Failed to open %s: %m", path);
|
||||
}
|
||||
|
||||
log_debug("apply: %s", pp);
|
||||
log_debug("apply: %s", path);
|
||||
for (;;) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
char *l;
|
||||
@ -84,7 +83,7 @@ static int apply_file(struct kmod_ctx *ctx, const char *path, bool ignore_enoent
|
||||
|
||||
k = read_line(f, LONG_LINE_MAX, &line);
|
||||
if (k < 0)
|
||||
return log_error_errno(k, "Failed to read file '%s': %m", pp);
|
||||
return log_error_errno(k, "Failed to read file '%s': %m", path);
|
||||
if (k == 0)
|
||||
break;
|
||||
|
||||
|
||||
@ -3577,7 +3577,7 @@ static int outer_child(
|
||||
DISSECT_IMAGE_MOUNT_ROOT_ONLY|
|
||||
DISSECT_IMAGE_DISCARD_ON_LOOP|
|
||||
DISSECT_IMAGE_USR_NO_ROOT|
|
||||
(arg_read_only ? DISSECT_IMAGE_READ_ONLY : DISSECT_IMAGE_FSCK|DISSECT_IMAGE_GROWFS)|
|
||||
(arg_read_only ? DISSECT_IMAGE_READ_ONLY : DISSECT_IMAGE_FSCK)|
|
||||
(arg_start_mode == START_BOOT ? DISSECT_IMAGE_VALIDATE_OS : 0));
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -3670,7 +3670,7 @@ static int outer_child(
|
||||
DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY|
|
||||
DISSECT_IMAGE_DISCARD_ON_LOOP|
|
||||
DISSECT_IMAGE_USR_NO_ROOT|
|
||||
(arg_read_only ? DISSECT_IMAGE_READ_ONLY : DISSECT_IMAGE_FSCK|DISSECT_IMAGE_GROWFS));
|
||||
(arg_read_only ? DISSECT_IMAGE_READ_ONLY : DISSECT_IMAGE_FSCK));
|
||||
if (r == -EUCLEAN)
|
||||
return log_error_errno(r, "File system check for image failed: %m");
|
||||
if (r < 0)
|
||||
|
||||
@ -54,7 +54,8 @@ enum nss_status _nss_myhostname_gethostbyname4_r(
|
||||
assert(h_errnop);
|
||||
|
||||
if (is_localhost(name)) {
|
||||
/* We respond to 'localhost', so that /etc/hosts is optional */
|
||||
/* We respond to 'localhost', so that /etc/hosts
|
||||
* is optional */
|
||||
|
||||
canonical = "localhost";
|
||||
local_address_ipv4 = htobe32(INADDR_LOOPBACK);
|
||||
@ -67,14 +68,6 @@ enum nss_status _nss_myhostname_gethostbyname4_r(
|
||||
|
||||
canonical = "_gateway";
|
||||
|
||||
} else if (is_outbound_hostname(name)) {
|
||||
|
||||
n_addresses = local_outbounds(NULL, 0, AF_UNSPEC, &addresses);
|
||||
if (n_addresses <= 0)
|
||||
goto not_found;
|
||||
|
||||
canonical = "_outbound";
|
||||
|
||||
} else {
|
||||
hn = gethostname_malloc();
|
||||
if (!hn) {
|
||||
@ -350,14 +343,6 @@ enum nss_status _nss_myhostname_gethostbyname3_r(
|
||||
|
||||
canonical = "_gateway";
|
||||
|
||||
} else if (is_outbound_hostname(name)) {
|
||||
|
||||
n_addresses = local_outbounds(NULL, 0, af, &addresses);
|
||||
if (n_addresses <= 0)
|
||||
goto not_found;
|
||||
|
||||
canonical = "_outbound";
|
||||
|
||||
} else {
|
||||
hn = gethostname_malloc();
|
||||
if (!hn) {
|
||||
|
||||
@ -294,8 +294,8 @@ static enum nss_status nss_systemd_endent(GetentData *p) {
|
||||
|
||||
assert(p);
|
||||
|
||||
_cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = pthread_mutex_lock_assert(&p->mutex);
|
||||
(void) _l; /* make llvm shut up about _l not being used. */
|
||||
_cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = NULL;
|
||||
_l = pthread_mutex_lock_assert(&p->mutex);
|
||||
|
||||
p->iterator = userdb_iterator_free(p->iterator);
|
||||
p->by_membership = false;
|
||||
@ -312,16 +312,16 @@ enum nss_status _nss_systemd_endgrent(void) {
|
||||
}
|
||||
|
||||
enum nss_status _nss_systemd_setpwent(int stayopen) {
|
||||
int r;
|
||||
|
||||
PROTECT_ERRNO;
|
||||
NSS_ENTRYPOINT_BEGIN;
|
||||
|
||||
if (_nss_systemd_is_blocked())
|
||||
return NSS_STATUS_NOTFOUND;
|
||||
|
||||
_cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = pthread_mutex_lock_assert(&getpwent_data.mutex);
|
||||
(void) _l; /* make llvm shut up about _l not being used. */
|
||||
_cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = NULL;
|
||||
int r;
|
||||
|
||||
_l = pthread_mutex_lock_assert(&getpwent_data.mutex);
|
||||
|
||||
getpwent_data.iterator = userdb_iterator_free(getpwent_data.iterator);
|
||||
getpwent_data.by_membership = false;
|
||||
@ -336,16 +336,16 @@ enum nss_status _nss_systemd_setpwent(int stayopen) {
|
||||
}
|
||||
|
||||
enum nss_status _nss_systemd_setgrent(int stayopen) {
|
||||
int r;
|
||||
|
||||
PROTECT_ERRNO;
|
||||
NSS_ENTRYPOINT_BEGIN;
|
||||
|
||||
if (_nss_systemd_is_blocked())
|
||||
return NSS_STATUS_NOTFOUND;
|
||||
|
||||
_cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = pthread_mutex_lock_assert(&getgrent_data.mutex);
|
||||
(void) _l; /* make llvm shut up about _l not being used. */
|
||||
_cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = NULL;
|
||||
int r;
|
||||
|
||||
_l = pthread_mutex_lock_assert(&getgrent_data.mutex);
|
||||
|
||||
getgrent_data.iterator = userdb_iterator_free(getgrent_data.iterator);
|
||||
getgrent_data.by_membership = false;
|
||||
@ -372,8 +372,9 @@ enum nss_status _nss_systemd_getpwent_r(
|
||||
if (_nss_systemd_is_blocked())
|
||||
return NSS_STATUS_NOTFOUND;
|
||||
|
||||
_cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = pthread_mutex_lock_assert(&getpwent_data.mutex);
|
||||
(void) _l; /* make llvm shut up about _l not being used. */
|
||||
_cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = NULL;
|
||||
|
||||
_l = pthread_mutex_lock_assert(&getpwent_data.mutex);
|
||||
|
||||
if (!getpwent_data.iterator) {
|
||||
UNPROTECT_ERRNO;
|
||||
@ -418,8 +419,9 @@ enum nss_status _nss_systemd_getgrent_r(
|
||||
if (_nss_systemd_is_blocked())
|
||||
return NSS_STATUS_NOTFOUND;
|
||||
|
||||
_cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = pthread_mutex_lock_assert(&getgrent_data.mutex);
|
||||
(void) _l; /* make llvm shut up about _l not being used. */
|
||||
_cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = NULL;
|
||||
|
||||
_l = pthread_mutex_lock_assert(&getgrent_data.mutex);
|
||||
|
||||
if (!getgrent_data.iterator) {
|
||||
UNPROTECT_ERRNO;
|
||||
|
||||
@ -170,7 +170,6 @@ struct Partition {
|
||||
|
||||
uint64_t gpt_flags;
|
||||
int read_only;
|
||||
int growfs;
|
||||
|
||||
LIST_FIELDS(Partition, partitions);
|
||||
};
|
||||
@ -244,7 +243,6 @@ static Partition *partition_new(void) {
|
||||
.copy_blocks_fd = -1,
|
||||
.copy_blocks_size = UINT64_MAX,
|
||||
.read_only = -1,
|
||||
.growfs = -1,
|
||||
};
|
||||
|
||||
return p;
|
||||
@ -1318,7 +1316,6 @@ static int partition_read_definition(Partition *p, const char *path) {
|
||||
{ "Partition", "Encrypt", config_parse_encrypt, 0, &p->encrypt },
|
||||
{ "Partition", "Flags", config_parse_gpt_flags, 0, &p->gpt_flags },
|
||||
{ "Partition", "ReadOnly", config_parse_tristate, 0, &p->read_only },
|
||||
{ "Partition", "GrowFileSystem", config_parse_tristate, 0, &p->growfs },
|
||||
{}
|
||||
};
|
||||
int r;
|
||||
@ -1366,11 +1363,6 @@ static int partition_read_definition(Partition *p, const char *path) {
|
||||
p->read_only < 0)
|
||||
p->read_only = true;
|
||||
|
||||
/* Default to "growfs" on, unless read-only */
|
||||
if (gpt_partition_type_knows_growfs(p->type_uuid) &&
|
||||
p->read_only <= 0)
|
||||
p->growfs = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3263,38 +3255,6 @@ static int set_gpt_flags(struct fdisk_partition *q, uint64_t flags) {
|
||||
return fdisk_partition_set_attrs(q, a);
|
||||
}
|
||||
|
||||
static uint64_t partition_merge_flags(Partition *p) {
|
||||
uint64_t f;
|
||||
|
||||
assert(p);
|
||||
|
||||
f = p->gpt_flags;
|
||||
|
||||
if (p->read_only >= 0) {
|
||||
if (gpt_partition_type_knows_read_only(p->type_uuid))
|
||||
SET_FLAG(f, GPT_FLAG_READ_ONLY, p->read_only);
|
||||
else {
|
||||
char buffer[ID128_UUID_STRING_MAX];
|
||||
log_warning("Configured ReadOnly=%s for partition type '%s' that doesn't support it, ignoring.",
|
||||
yes_no(p->read_only),
|
||||
gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
|
||||
}
|
||||
}
|
||||
|
||||
if (p->growfs >= 0) {
|
||||
if (gpt_partition_type_knows_growfs(p->type_uuid))
|
||||
SET_FLAG(f, GPT_FLAG_GROWFS, p->growfs);
|
||||
else {
|
||||
char buffer[ID128_UUID_STRING_MAX];
|
||||
log_warning("Configured GrowFileSystem=%s for partition type '%s' that doesn't support it, ignoring.",
|
||||
yes_no(p->growfs),
|
||||
gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
|
||||
}
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
static int context_mangle_partitions(Context *context) {
|
||||
Partition *p;
|
||||
int r;
|
||||
@ -3363,6 +3323,7 @@ static int context_mangle_partitions(Context *context) {
|
||||
_cleanup_(fdisk_unref_partitionp) struct fdisk_partition *q = NULL;
|
||||
_cleanup_(fdisk_unref_parttypep) struct fdisk_parttype *t = NULL;
|
||||
char ids[ID128_UUID_STRING_MAX];
|
||||
uint64_t f;
|
||||
|
||||
assert(!p->new_partition);
|
||||
assert(p->offset % 512 == 0);
|
||||
@ -3410,8 +3371,19 @@ static int context_mangle_partitions(Context *context) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set partition label: %m");
|
||||
|
||||
/* Merge the read only + growfs setting with the literal flags, and set them for the partition */
|
||||
r = set_gpt_flags(q, partition_merge_flags(p));
|
||||
/* Merge the read only setting with the literal flags */
|
||||
f = p->gpt_flags;
|
||||
if (p->read_only >= 0) {
|
||||
if (gpt_partition_type_knows_read_only(p->type_uuid))
|
||||
SET_FLAG(f, GPT_FLAG_READ_ONLY, p->read_only);
|
||||
else {
|
||||
char buffer[ID128_UUID_STRING_MAX];
|
||||
log_warning("Configured ReadOnly=yes for partition type '%s' that doesn't support it, ignoring.",
|
||||
gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
|
||||
}
|
||||
}
|
||||
|
||||
r = set_gpt_flags(q, f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set GPT partition flags: %m");
|
||||
|
||||
|
||||
@ -65,9 +65,9 @@ device: $D/zzz
|
||||
unit: sectors
|
||||
first-lba: 2048
|
||||
last-lba: 2097118
|
||||
$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first", attrs="GUID:59"
|
||||
$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64", attrs="GUID:59"
|
||||
$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2", attrs="GUID:59"
|
||||
$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first"
|
||||
$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64"
|
||||
$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2"
|
||||
$D/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
|
||||
EOF
|
||||
|
||||
@ -100,9 +100,9 @@ device: $D/zzz
|
||||
unit: sectors
|
||||
first-lba: 2048
|
||||
last-lba: 2097118
|
||||
$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first", attrs="GUID:59"
|
||||
$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64", attrs="GUID:59"
|
||||
$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2", attrs="GUID:59"
|
||||
$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first"
|
||||
$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64"
|
||||
$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2"
|
||||
$D/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
|
||||
$D/zzz5 : start= 1908696, size= 188416, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name="custom_label"
|
||||
EOF
|
||||
@ -120,9 +120,9 @@ device: $D/zzz
|
||||
unit: sectors
|
||||
first-lba: 2048
|
||||
last-lba: 4194270
|
||||
$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first", attrs="GUID:59"
|
||||
$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64", attrs="GUID:59"
|
||||
$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2", attrs="GUID:59"
|
||||
$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first"
|
||||
$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64"
|
||||
$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2"
|
||||
$D/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
|
||||
$D/zzz5 : start= 1908696, size= 2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name="custom_label"
|
||||
EOF
|
||||
@ -150,9 +150,9 @@ device: $D/zzz
|
||||
unit: sectors
|
||||
first-lba: 2048
|
||||
last-lba: 6291422
|
||||
$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first", attrs="GUID:59"
|
||||
$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64", attrs="GUID:59"
|
||||
$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2", attrs="GUID:59"
|
||||
$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first"
|
||||
$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64"
|
||||
$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2"
|
||||
$D/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
|
||||
$D/zzz5 : start= 1908696, size= 2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name="custom_label"
|
||||
$D/zzz6 : start= 4194264, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=2A1D97E1-D0A3-46CC-A26E-ADC643926617, name="block-copy"
|
||||
@ -187,9 +187,9 @@ device: $D/zzz
|
||||
unit: sectors
|
||||
first-lba: 2048
|
||||
last-lba: 6389726
|
||||
$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first", attrs="GUID:59"
|
||||
$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64", attrs="GUID:59"
|
||||
$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2", attrs="GUID:59"
|
||||
$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first"
|
||||
$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64"
|
||||
$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2"
|
||||
$D/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
|
||||
$D/zzz5 : start= 1908696, size= 2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name="custom_label"
|
||||
$D/zzz6 : start= 4194264, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=2A1D97E1-D0A3-46CC-A26E-ADC643926617, name="block-copy"
|
||||
|
||||
@ -630,8 +630,8 @@ DnsScopeMatch dns_scope_good_domain(
|
||||
if (dns_name_endswith(domain, "invalid") > 0)
|
||||
return DNS_SCOPE_NO;
|
||||
|
||||
/* Never go to network for the _gateway or _outbound domain — they're something special, synthesized locally. */
|
||||
if (is_gateway_hostname(domain) || is_outbound_hostname(domain))
|
||||
/* Never go to network for the _gateway domain, it's something special, synthesized locally. */
|
||||
if (is_gateway_hostname(domain))
|
||||
return DNS_SCOPE_NO;
|
||||
|
||||
switch (s->protocol) {
|
||||
@ -739,7 +739,6 @@ DnsScopeMatch dns_scope_good_domain(
|
||||
|
||||
if ((dns_name_is_single_label(domain) && /* only resolve single label names via LLMNR */
|
||||
!is_gateway_hostname(domain) && /* don't resolve "_gateway" with LLMNR, let local synthesizing logic handle that */
|
||||
!is_outbound_hostname(domain) && /* similar for "_outbound" */
|
||||
dns_name_equal(domain, "local") == 0 && /* don't resolve "local" with LLMNR, it's the top-level domain of mDNS after all, see above */
|
||||
manager_is_own_hostname(s->manager, domain) <= 0)) /* never resolve the local hostname via LLMNR */
|
||||
return DNS_SCOPE_YES_BASE + 1; /* Return +1, as we consider ourselves authoritative
|
||||
|
||||
@ -311,33 +311,27 @@ static int synthesize_system_hostname_ptr(Manager *m, int af, const union in_add
|
||||
return added;
|
||||
}
|
||||
|
||||
static int synthesize_gateway_rr(
|
||||
Manager *m,
|
||||
const DnsResourceKey *key,
|
||||
int ifindex,
|
||||
int (*lookup)(sd_netlink *context, int ifindex, int af, struct local_address **ret), /* either local_gateways() or local_outbound() */
|
||||
DnsAnswer **answer) {
|
||||
static int synthesize_gateway_rr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) {
|
||||
_cleanup_free_ struct local_address *addresses = NULL;
|
||||
int n = 0, af, r;
|
||||
|
||||
assert(m);
|
||||
assert(key);
|
||||
assert(lookup);
|
||||
assert(answer);
|
||||
|
||||
af = dns_type_to_af(key->type);
|
||||
if (af >= 0) {
|
||||
n = lookup(m->rtnl, ifindex, af, &addresses);
|
||||
n = local_gateways(m->rtnl, ifindex, af, &addresses);
|
||||
if (n < 0) /* < 0 means: error */
|
||||
return n;
|
||||
|
||||
if (n == 0) { /* == 0 means we have no gateway */
|
||||
/* See if there's a gateway on the other protocol */
|
||||
if (af == AF_INET)
|
||||
n = lookup(m->rtnl, ifindex, AF_INET6, NULL);
|
||||
n = local_gateways(m->rtnl, ifindex, AF_INET6, NULL);
|
||||
else {
|
||||
assert(af == AF_INET6);
|
||||
n = lookup(m->rtnl, ifindex, AF_INET, NULL);
|
||||
n = local_gateways(m->rtnl, ifindex, AF_INET, NULL);
|
||||
}
|
||||
if (n <= 0) /* error (if < 0) or really no gateway at all (if == 0) */
|
||||
return n;
|
||||
@ -408,7 +402,7 @@ int dns_synthesize_answer(
|
||||
|
||||
} else if (is_gateway_hostname(name)) {
|
||||
|
||||
r = synthesize_gateway_rr(m, key, ifindex, local_gateways, &answer);
|
||||
r = synthesize_gateway_rr(m, key, ifindex, &answer);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to synthesize gateway RRs: %m");
|
||||
if (r == 0) { /* if we have no gateway return NXDOMAIN */
|
||||
@ -416,16 +410,6 @@ int dns_synthesize_answer(
|
||||
continue;
|
||||
}
|
||||
|
||||
} else if (is_outbound_hostname(name)) {
|
||||
|
||||
r = synthesize_gateway_rr(m, key, ifindex, local_outbounds, &answer);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to synthesize outbound RRs: %m");
|
||||
if (r == 0) { /* if we have no gateway return NXDOMAIN */
|
||||
nxdomain = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
} else if ((dns_name_endswith(name, "127.in-addr.arpa") > 0 && dns_name_equal(name, "2.0.0.127.in-addr.arpa") == 0) ||
|
||||
dns_name_equal(name, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0) {
|
||||
|
||||
@ -447,10 +431,6 @@ int dns_synthesize_answer(
|
||||
if (v == 0 && w == 0) /* This IP address is neither a local one nor a gateway */
|
||||
continue;
|
||||
|
||||
/* Note that we never synthesize reverse PTR for _outbound, since those are local
|
||||
* addresses and thus mapped to the local hostname anyway, hence they already have a
|
||||
* mapping. */
|
||||
|
||||
} else
|
||||
continue;
|
||||
|
||||
|
||||
@ -250,7 +250,7 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
|
||||
while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &str)) > 0) {
|
||||
_cleanup_free_ char *e = NULL;
|
||||
|
||||
e = shell_maybe_quote(str, 0);
|
||||
e = shell_maybe_quote(str, ESCAPE_BACKSLASH_ONELINE);
|
||||
if (!e)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
@ -181,7 +181,7 @@ static void log_job_error_with_service_result(const char* service, const char *r
|
||||
|
||||
assert(service);
|
||||
|
||||
service_shell_quoted = shell_maybe_quote(service, 0);
|
||||
service_shell_quoted = shell_maybe_quote(service, ESCAPE_BACKSLASH);
|
||||
|
||||
if (!strv_isempty((char**) extra_args)) {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
|
||||
@ -46,7 +46,6 @@
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "raw-clone.h"
|
||||
#include "resize-fs.h"
|
||||
#include "signal-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "stdio-util.h"
|
||||
@ -535,8 +534,7 @@ int dissect_image(
|
||||
sd_id128_t usr_uuid = SD_ID128_NULL, usr_verity_uuid = SD_ID128_NULL;
|
||||
#endif
|
||||
bool is_gpt, is_mbr, multiple_generic = false,
|
||||
generic_rw = false, /* initialize to appease gcc */
|
||||
generic_growfs = false;
|
||||
generic_rw = false; /* initialize to appease gcc */
|
||||
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
|
||||
_cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
|
||||
_cleanup_(blkid_free_probep) blkid_probe b = NULL;
|
||||
@ -797,7 +795,7 @@ int dissect_image(
|
||||
int architecture = _ARCHITECTURE_INVALID;
|
||||
const char *stype, *sid, *fstype = NULL, *label;
|
||||
sd_id128_t type_id, id;
|
||||
bool rw = true, growfs = false;
|
||||
bool rw = true;
|
||||
|
||||
sid = blkid_partition_get_uuid(pp);
|
||||
if (!sid)
|
||||
@ -815,25 +813,23 @@ int dissect_image(
|
||||
|
||||
if (sd_id128_equal(type_id, GPT_HOME)) {
|
||||
|
||||
check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
|
||||
check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
|
||||
|
||||
if (pflags & GPT_FLAG_NO_AUTO)
|
||||
continue;
|
||||
|
||||
designator = PARTITION_HOME;
|
||||
rw = !(pflags & GPT_FLAG_READ_ONLY);
|
||||
growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
|
||||
|
||||
} else if (sd_id128_equal(type_id, GPT_SRV)) {
|
||||
|
||||
check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
|
||||
check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
|
||||
|
||||
if (pflags & GPT_FLAG_NO_AUTO)
|
||||
continue;
|
||||
|
||||
designator = PARTITION_SRV;
|
||||
rw = !(pflags & GPT_FLAG_READ_ONLY);
|
||||
growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
|
||||
|
||||
} else if (sd_id128_equal(type_id, GPT_ESP)) {
|
||||
|
||||
@ -850,19 +846,18 @@ int dissect_image(
|
||||
|
||||
} else if (sd_id128_equal(type_id, GPT_XBOOTLDR)) {
|
||||
|
||||
check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
|
||||
check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
|
||||
|
||||
if (pflags & GPT_FLAG_NO_AUTO)
|
||||
continue;
|
||||
|
||||
designator = PARTITION_XBOOTLDR;
|
||||
rw = !(pflags & GPT_FLAG_READ_ONLY);
|
||||
growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
|
||||
}
|
||||
#ifdef GPT_ROOT_NATIVE
|
||||
else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE)) {
|
||||
|
||||
check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
|
||||
check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
|
||||
|
||||
if (pflags & GPT_FLAG_NO_AUTO)
|
||||
continue;
|
||||
@ -874,7 +869,6 @@ int dissect_image(
|
||||
designator = PARTITION_ROOT;
|
||||
architecture = native_architecture();
|
||||
rw = !(pflags & GPT_FLAG_READ_ONLY);
|
||||
growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
|
||||
|
||||
} else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE_VERITY)) {
|
||||
|
||||
@ -898,7 +892,7 @@ int dissect_image(
|
||||
#ifdef GPT_ROOT_SECONDARY
|
||||
else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY)) {
|
||||
|
||||
check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
|
||||
check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
|
||||
|
||||
if (pflags & GPT_FLAG_NO_AUTO)
|
||||
continue;
|
||||
@ -910,7 +904,6 @@ int dissect_image(
|
||||
designator = PARTITION_ROOT_SECONDARY;
|
||||
architecture = SECONDARY_ARCHITECTURE;
|
||||
rw = !(pflags & GPT_FLAG_READ_ONLY);
|
||||
growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
|
||||
|
||||
} else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY_VERITY)) {
|
||||
|
||||
@ -934,7 +927,7 @@ int dissect_image(
|
||||
#ifdef GPT_USR_NATIVE
|
||||
else if (sd_id128_equal(type_id, GPT_USR_NATIVE)) {
|
||||
|
||||
check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
|
||||
check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
|
||||
|
||||
if (pflags & GPT_FLAG_NO_AUTO)
|
||||
continue;
|
||||
@ -946,7 +939,6 @@ int dissect_image(
|
||||
designator = PARTITION_USR;
|
||||
architecture = native_architecture();
|
||||
rw = !(pflags & GPT_FLAG_READ_ONLY);
|
||||
growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
|
||||
|
||||
} else if (sd_id128_equal(type_id, GPT_USR_NATIVE_VERITY)) {
|
||||
|
||||
@ -970,7 +962,7 @@ int dissect_image(
|
||||
#ifdef GPT_USR_SECONDARY
|
||||
else if (sd_id128_equal(type_id, GPT_USR_SECONDARY)) {
|
||||
|
||||
check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
|
||||
check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
|
||||
|
||||
if (pflags & GPT_FLAG_NO_AUTO)
|
||||
continue;
|
||||
@ -982,7 +974,6 @@ int dissect_image(
|
||||
designator = PARTITION_USR_SECONDARY;
|
||||
architecture = SECONDARY_ARCHITECTURE;
|
||||
rw = !(pflags & GPT_FLAG_READ_ONLY);
|
||||
growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
|
||||
|
||||
} else if (sd_id128_equal(type_id, GPT_USR_SECONDARY_VERITY)) {
|
||||
|
||||
@ -1015,7 +1006,7 @@ int dissect_image(
|
||||
|
||||
} else if (sd_id128_equal(type_id, GPT_LINUX_GENERIC)) {
|
||||
|
||||
check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
|
||||
check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
|
||||
|
||||
if (pflags & GPT_FLAG_NO_AUTO)
|
||||
continue;
|
||||
@ -1025,7 +1016,6 @@ int dissect_image(
|
||||
else {
|
||||
generic_nr = nr;
|
||||
generic_rw = !(pflags & GPT_FLAG_READ_ONLY);
|
||||
generic_growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
|
||||
generic_uuid = id;
|
||||
generic_node = strdup(node);
|
||||
if (!generic_node)
|
||||
@ -1034,18 +1024,17 @@ int dissect_image(
|
||||
|
||||
} else if (sd_id128_equal(type_id, GPT_TMP)) {
|
||||
|
||||
check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
|
||||
check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
|
||||
|
||||
if (pflags & GPT_FLAG_NO_AUTO)
|
||||
continue;
|
||||
|
||||
designator = PARTITION_TMP;
|
||||
rw = !(pflags & GPT_FLAG_READ_ONLY);
|
||||
growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
|
||||
|
||||
} else if (sd_id128_equal(type_id, GPT_VAR)) {
|
||||
|
||||
check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
|
||||
check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
|
||||
|
||||
if (pflags & GPT_FLAG_NO_AUTO)
|
||||
continue;
|
||||
@ -1073,7 +1062,6 @@ int dissect_image(
|
||||
|
||||
designator = PARTITION_VAR;
|
||||
rw = !(pflags & GPT_FLAG_READ_ONLY);
|
||||
growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
|
||||
}
|
||||
|
||||
if (designator != _PARTITION_DESIGNATOR_INVALID) {
|
||||
@ -1120,7 +1108,6 @@ int dissect_image(
|
||||
.found = true,
|
||||
.partno = nr,
|
||||
.rw = rw,
|
||||
.growfs = growfs,
|
||||
.architecture = architecture,
|
||||
.node = TAKE_PTR(n),
|
||||
.fstype = TAKE_PTR(t),
|
||||
@ -1144,7 +1131,6 @@ int dissect_image(
|
||||
else {
|
||||
generic_nr = nr;
|
||||
generic_rw = true;
|
||||
generic_growfs = false;
|
||||
generic_node = strdup(node);
|
||||
if (!generic_node)
|
||||
return -ENOMEM;
|
||||
@ -1180,7 +1166,6 @@ int dissect_image(
|
||||
.found = true,
|
||||
.partno = nr,
|
||||
.rw = true,
|
||||
.growfs = false,
|
||||
.architecture = _ARCHITECTURE_INVALID,
|
||||
.node = TAKE_PTR(n),
|
||||
.uuid = id,
|
||||
@ -1269,7 +1254,6 @@ int dissect_image(
|
||||
m->partitions[PARTITION_ROOT] = (DissectedPartition) {
|
||||
.found = true,
|
||||
.rw = generic_rw,
|
||||
.growfs = generic_growfs,
|
||||
.partno = generic_nr,
|
||||
.architecture = _ARCHITECTURE_INVALID,
|
||||
.node = TAKE_PTR(generic_node),
|
||||
@ -1332,9 +1316,6 @@ int dissect_image(
|
||||
|
||||
if (p->fstype && fstype_is_ro(p->fstype))
|
||||
p->rw = false;
|
||||
|
||||
if (!p->rw)
|
||||
p->growfs = false;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
@ -1430,43 +1411,6 @@ static int run_fsck(const char *node, const char *fstype) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fs_grow(const char *node_path, const char *mount_path) {
|
||||
_cleanup_close_ int mount_fd = -1, node_fd = -1;
|
||||
char fb[FORMAT_BYTES_MAX];
|
||||
uint64_t size, newsize;
|
||||
int r;
|
||||
|
||||
node_fd = open(node_path, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
|
||||
if (node_fd < 0)
|
||||
return log_debug_errno(errno, "Failed to open node device %s: %m", node_path);
|
||||
|
||||
if (ioctl(node_fd, BLKGETSIZE64, &size) != 0)
|
||||
return log_debug_errno(errno, "Failed to get block device size of %s: %m", node_path);
|
||||
|
||||
mount_fd = open(mount_path, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
|
||||
if (mount_fd < 0)
|
||||
return log_debug_errno(errno, "Failed to open mountd file system %s: %m", mount_path);
|
||||
|
||||
log_debug("Resizing \"%s\" to %"PRIu64" bytes...", mount_path, size);
|
||||
r = resize_fs(mount_fd, size, &newsize);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to resize \"%s\" to %"PRIu64" bytes: %m", mount_path, size);
|
||||
|
||||
if (newsize == size)
|
||||
log_debug("Successfully resized \"%s\" to %s bytes.",
|
||||
mount_path,
|
||||
format_bytes(fb, sizeof fb, newsize));
|
||||
else {
|
||||
assert(newsize < size);
|
||||
log_debug("Successfully resized \"%s\" to %s bytes (%"PRIu64" bytes lost due to blocksize).",
|
||||
mount_path,
|
||||
format_bytes(fb, sizeof fb, newsize),
|
||||
size - newsize);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mount_partition(
|
||||
DissectedPartition *m,
|
||||
const char *where,
|
||||
@ -1575,9 +1519,6 @@ static int mount_partition(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (rw && m->growfs && FLAGS_SET(flags, DISSECT_IMAGE_GROWFS))
|
||||
(void) fs_grow(node, p);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -18,7 +18,6 @@ typedef struct VeritySettings VeritySettings;
|
||||
struct DissectedPartition {
|
||||
bool found:1;
|
||||
bool rw:1;
|
||||
bool growfs:1;
|
||||
int partno; /* -1 if there was no partition and the images contains a file system directly */
|
||||
int architecture; /* Intended architecture: either native, secondary or unset (-1). */
|
||||
sd_id128_t uuid; /* Partition entry UUID as reported by the GPT */
|
||||
@ -111,7 +110,6 @@ typedef enum DissectImageFlags {
|
||||
DISSECT_IMAGE_MOUNT_READ_ONLY = 1 << 17, /* Make mounts read-only */
|
||||
DISSECT_IMAGE_READ_ONLY = DISSECT_IMAGE_DEVICE_READ_ONLY |
|
||||
DISSECT_IMAGE_MOUNT_READ_ONLY,
|
||||
DISSECT_IMAGE_GROWFS = 1 << 18, /* Grow file systems in partitions marked for that to the size of the partitions after mount */
|
||||
} DissectImageFlags;
|
||||
|
||||
struct DissectedImage {
|
||||
|
||||
@ -503,9 +503,6 @@ int generator_hook_up_growfs(
|
||||
const char *unit_file;
|
||||
int r;
|
||||
|
||||
assert(dir);
|
||||
assert(where);
|
||||
|
||||
escaped = cescape(where);
|
||||
if (!escaped)
|
||||
return log_oom();
|
||||
@ -537,10 +534,9 @@ int generator_hook_up_growfs(
|
||||
"BindsTo=%%i.mount\n"
|
||||
"Conflicts=shutdown.target\n"
|
||||
"After=%%i.mount\n"
|
||||
"Before=shutdown.target%s%s\n",
|
||||
"Before=shutdown.target %s\n",
|
||||
program_invocation_short_name,
|
||||
target ? " " : "",
|
||||
strempty(target));
|
||||
target);
|
||||
|
||||
if (empty_or_root(where)) /* Make sure the root fs is actually writable before we resize it */
|
||||
fprintf(f,
|
||||
|
||||
@ -163,14 +163,3 @@ bool gpt_partition_type_knows_read_only(sd_id128_t id) {
|
||||
gpt_partition_type_is_root_verity(id) || /* pretty much implied, but let's set the bit to make things really clear */
|
||||
gpt_partition_type_is_usr_verity(id); /* ditto */
|
||||
}
|
||||
|
||||
bool gpt_partition_type_knows_growfs(sd_id128_t id) {
|
||||
return gpt_partition_type_is_root(id) ||
|
||||
gpt_partition_type_is_usr(id) ||
|
||||
sd_id128_in_set(id,
|
||||
GPT_HOME,
|
||||
GPT_SRV,
|
||||
GPT_VAR,
|
||||
GPT_TMP,
|
||||
GPT_XBOOTLDR);
|
||||
}
|
||||
|
||||
@ -113,7 +113,6 @@
|
||||
* but that's just because we saw no point in defining any other values here. */
|
||||
#define GPT_FLAG_READ_ONLY (1ULL << 60)
|
||||
#define GPT_FLAG_NO_AUTO (1ULL << 63)
|
||||
#define GPT_FLAG_GROWFS (1ULL << 59)
|
||||
|
||||
const char *gpt_partition_type_uuid_to_string(sd_id128_t id);
|
||||
const char *gpt_partition_type_uuid_to_string_harder(
|
||||
@ -136,4 +135,3 @@ bool gpt_partition_type_is_usr(sd_id128_t id);
|
||||
bool gpt_partition_type_is_usr_verity(sd_id128_t id);
|
||||
|
||||
bool gpt_partition_type_knows_read_only(sd_id128_t id);
|
||||
bool gpt_partition_type_knows_growfs(sd_id128_t id);
|
||||
|
||||
@ -1,11 +1,8 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <net/if_arp.h>
|
||||
|
||||
#include "sd-netlink.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "local-addresses.h"
|
||||
#include "macro.h"
|
||||
#include "netlink-util.h"
|
||||
@ -36,34 +33,7 @@ static int address_compare(const struct local_address *a, const struct local_add
|
||||
return memcmp(&a->address, &b->address, FAMILY_ADDRESS_SIZE(a->family));
|
||||
}
|
||||
|
||||
static void suppress_duplicates(struct local_address *list, size_t *n_list) {
|
||||
size_t old_size, new_size;
|
||||
|
||||
/* Removes duplicate entries, assumes the list of addresses is already sorted. Updates in-place. */
|
||||
|
||||
if (*n_list < 2) /* list with less than two entries can't have duplicates */
|
||||
return;
|
||||
|
||||
old_size = *n_list;
|
||||
new_size = 1;
|
||||
|
||||
for (size_t i = 1; i < old_size; i++) {
|
||||
|
||||
if (address_compare(list + i, list + new_size - 1) == 0)
|
||||
continue;
|
||||
|
||||
list[new_size++] = list[i];
|
||||
}
|
||||
|
||||
*n_list = new_size;
|
||||
}
|
||||
|
||||
int local_addresses(
|
||||
sd_netlink *context,
|
||||
int ifindex,
|
||||
int af,
|
||||
struct local_address **ret) {
|
||||
|
||||
int local_addresses(sd_netlink *context, int ifindex, int af, struct local_address **ret) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
||||
_cleanup_free_ struct local_address *list = NULL;
|
||||
@ -165,7 +135,6 @@ int local_addresses(
|
||||
|
||||
if (ret) {
|
||||
typesafe_qsort(list, n_list, address_compare);
|
||||
suppress_duplicates(list, &n_list);
|
||||
*ret = TAKE_PTR(list);
|
||||
}
|
||||
|
||||
@ -202,12 +171,7 @@ static int add_local_gateway(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int local_gateways(
|
||||
sd_netlink *context,
|
||||
int ifindex,
|
||||
int af,
|
||||
struct local_address **ret) {
|
||||
|
||||
int local_gateways(sd_netlink *context, int ifindex, int af, struct local_address **ret) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
||||
_cleanup_free_ struct local_address *list = NULL;
|
||||
@ -344,151 +308,6 @@ int local_gateways(
|
||||
|
||||
if (ret) {
|
||||
typesafe_qsort(list, n_list, address_compare);
|
||||
suppress_duplicates(list, &n_list);
|
||||
*ret = TAKE_PTR(list);
|
||||
}
|
||||
|
||||
return (int) n_list;
|
||||
}
|
||||
|
||||
int local_outbounds(
|
||||
sd_netlink *context,
|
||||
int ifindex,
|
||||
int af,
|
||||
struct local_address **ret) {
|
||||
|
||||
_cleanup_free_ struct local_address *list = NULL, *gateways = NULL;
|
||||
size_t n_list = 0, n_allocated = 0;
|
||||
int r, n_gateways;
|
||||
|
||||
/* Determines our default outbound addresses, i.e. the "primary" local addresses we use to talk to IP
|
||||
* addresses behind the default routes. This is still an address of the local host (i.e. this doesn't
|
||||
* resolve NAT or so), but it's the set of addresses the local IP stack most likely uses to talk to
|
||||
* other hosts.
|
||||
*
|
||||
* This works by connect()ing a SOCK_DGRAM socket to the local gateways, and then reading the IP
|
||||
* address off the socket that was chosen for the routing decision. */
|
||||
|
||||
n_gateways = local_gateways(context, ifindex, af, &gateways);
|
||||
if (n_gateways < 0)
|
||||
return n_gateways;
|
||||
if (n_gateways == 0) {
|
||||
/* No gateways? Then we have no outbound addresses either. */
|
||||
if (ret)
|
||||
*ret = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < n_gateways; i++) {
|
||||
_cleanup_close_ int fd = -1;
|
||||
union sockaddr_union sa;
|
||||
socklen_t salen;
|
||||
|
||||
fd = socket(gateways[i].family, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
switch (gateways[i].family) {
|
||||
|
||||
case AF_INET:
|
||||
sa.in = (struct sockaddr_in) {
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr = gateways[i].address.in,
|
||||
.sin_port = htobe16(53), /* doesn't really matter which port we pick — we just care about the routing decision */
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
sa.in6 = (struct sockaddr_in6) {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_addr = gateways[i].address.in6,
|
||||
.sin6_port = htobe16(53),
|
||||
.sin6_scope_id = gateways[i].ifindex,
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached("Unexpected protocol");
|
||||
}
|
||||
|
||||
/* So ideally we'd just use IP_UNICAST_IF here to pass the ifindex info to the kernel before
|
||||
* connect()ing, sot that it influences the routing decision. However, on current kernels
|
||||
* IP_UNICAST_IF doesn't actually influence the routing decision for UDP — which I think
|
||||
* should probably just be considered a bug. Once that bug is fixed this is the best API to
|
||||
* use, since it is the most lightweight. */
|
||||
r = socket_set_unicast_if(fd, gateways[i].family, gateways[i].ifindex);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to set unicast interface index %i, ignoring: %m", gateways[i].ifindex);
|
||||
|
||||
/* We'll also use SO_BINDTOINDEX. This requires CAP_NET_RAW on old kernels, hence there's a
|
||||
* good chance this fails. Since 5.7 this restriction was dropped and the first
|
||||
* SO_BINDTOINDEX on a socket may be done without privileges. This one has the benefit of
|
||||
* really influencing the routing decision, i.e. this one definitely works for us — as long
|
||||
* as we have the privileges for it.*/
|
||||
r = socket_bind_to_ifindex(fd, gateways[i].ifindex);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to bind socket to interface %i, ignoring: %m", gateways[i].ifindex);
|
||||
|
||||
/* Let's now connect() to the UDP socket, forcing the kernel to make a routing decision and
|
||||
* auto-bind the socket. We ignore failures on this, since that failure might happen for a
|
||||
* multitude of reasons (policy/firewall issues, who knows?) and some of them might be
|
||||
* *after* the routing decision and the auto-binding already took place. If so we can still
|
||||
* make use of the binding and return it. Hence, let's not unnecessarily fail early here: we
|
||||
* can still easily detect if the auto-binding worked or not, by comparing the bound IP
|
||||
* address with zero — which we do below. */
|
||||
if (connect(fd, &sa.sa, SOCKADDR_LEN(sa)) < 0)
|
||||
log_debug_errno(errno, "Failed to connect SOCK_DGRAM socket to gateway, ignoring: %m");
|
||||
|
||||
/* Let's now read the socket address of the socket. A routing decision should have been
|
||||
* made. Let's verify that and use the data. */
|
||||
salen = SOCKADDR_LEN(sa);
|
||||
if (getsockname(fd, &sa.sa, &salen) < 0)
|
||||
return -errno;
|
||||
assert(sa.sa.sa_family == gateways[i].family);
|
||||
assert(salen == SOCKADDR_LEN(sa));
|
||||
|
||||
switch (gateways[i].family) {
|
||||
|
||||
case AF_INET:
|
||||
if (in4_addr_is_null(&sa.in.sin_addr)) /* Auto-binding didn't work. :-( */
|
||||
continue;
|
||||
|
||||
if (!GREEDY_REALLOC(list, n_allocated, n_list+1))
|
||||
return -ENOMEM;
|
||||
|
||||
list[n_list++] = (struct local_address) {
|
||||
.family = gateways[i].family,
|
||||
.ifindex = gateways[i].ifindex,
|
||||
.address.in = sa.in.sin_addr,
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
if (in6_addr_is_null(&sa.in6.sin6_addr))
|
||||
continue;
|
||||
|
||||
if (!GREEDY_REALLOC(list, n_allocated, n_list+1))
|
||||
return -ENOMEM;
|
||||
|
||||
list[n_list++] = (struct local_address) {
|
||||
.family = gateways[i].family,
|
||||
.ifindex = gateways[i].ifindex,
|
||||
.address.in6 = sa.in6.sin6_addr,
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached("Unexpected protocol");
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
typesafe_qsort(list, n_list, address_compare);
|
||||
suppress_duplicates(list, &n_list);
|
||||
*ret = TAKE_PTR(list);
|
||||
}
|
||||
|
||||
|
||||
@ -15,5 +15,3 @@ struct local_address {
|
||||
int local_addresses(sd_netlink *rtnl, int ifindex, int af, struct local_address **ret);
|
||||
|
||||
int local_gateways(sd_netlink *rtnl, int ifindex, int af, struct local_address **ret);
|
||||
|
||||
int local_outbounds(sd_netlink *rtnl, int ifindex, int af, struct local_address **ret);
|
||||
|
||||
@ -182,13 +182,12 @@ static int apply_all(OrderedHashmap *sysctl_options) {
|
||||
|
||||
static int parse_file(OrderedHashmap **sysctl_options, const char *path, bool ignore_enoent) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_free_ char *pp = NULL;
|
||||
unsigned c = 0;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
|
||||
r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("sysctl.d"), &f, &pp);
|
||||
r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("sysctl.d"), &f);
|
||||
if (r < 0) {
|
||||
if (ignore_enoent && r == -ENOENT)
|
||||
return 0;
|
||||
@ -196,7 +195,7 @@ static int parse_file(OrderedHashmap **sysctl_options, const char *path, bool ig
|
||||
return log_error_errno(r, "Failed to open file '%s', ignoring: %m", path);
|
||||
}
|
||||
|
||||
log_debug("Parsing %s", pp);
|
||||
log_debug("Parsing %s", path);
|
||||
for (;;) {
|
||||
_cleanup_(option_freep) Option *new_option = NULL;
|
||||
_cleanup_free_ char *l = NULL;
|
||||
@ -209,7 +208,7 @@ static int parse_file(OrderedHashmap **sysctl_options, const char *path, bool ig
|
||||
if (k == 0)
|
||||
break;
|
||||
if (k < 0)
|
||||
return log_error_errno(k, "Failed to read file '%s', ignoring: %m", pp);
|
||||
return log_error_errno(k, "Failed to read file '%s', ignoring: %m", path);
|
||||
|
||||
c++;
|
||||
|
||||
@ -236,7 +235,7 @@ static int parse_file(OrderedHashmap **sysctl_options, const char *path, bool ig
|
||||
/* We have a "negative match" option. Let's continue with value==NULL. */
|
||||
p++;
|
||||
else {
|
||||
log_syntax(NULL, LOG_WARNING, pp, c, 0,
|
||||
log_syntax(NULL, LOG_WARNING, path, c, 0,
|
||||
"Line is not an assignment, ignoring: %s", p);
|
||||
if (r == 0)
|
||||
r = -EINVAL;
|
||||
@ -262,7 +261,7 @@ static int parse_file(OrderedHashmap **sysctl_options, const char *path, bool ig
|
||||
continue;
|
||||
}
|
||||
|
||||
log_debug("Overwriting earlier assignment of %s at '%s:%u'.", p, pp, c);
|
||||
log_debug("Overwriting earlier assignment of %s at '%s:%u'.", p, path, c);
|
||||
option_free(ordered_hashmap_remove(*sysctl_options, p));
|
||||
}
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ static int print_variable(const char *s) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN),
|
||||
"Invalid environment block");
|
||||
|
||||
esc = shell_maybe_quote(sep + 1, SHELL_ESCAPE_POSIX);
|
||||
esc = shell_maybe_quote(sep + 1, ESCAPE_POSIX);
|
||||
if (!esc)
|
||||
return log_oom();
|
||||
|
||||
|
||||
@ -1728,7 +1728,6 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
|
||||
|
||||
static int read_config_file(const char *fn, bool ignore_enoent) {
|
||||
_cleanup_fclose_ FILE *rf = NULL;
|
||||
_cleanup_free_ char *pp = NULL;
|
||||
FILE *f = NULL;
|
||||
unsigned v = 0;
|
||||
int r = 0;
|
||||
@ -1738,7 +1737,7 @@ static int read_config_file(const char *fn, bool ignore_enoent) {
|
||||
if (streq(fn, "-"))
|
||||
f = stdin;
|
||||
else {
|
||||
r = search_and_fopen(fn, "re", arg_root, (const char**) CONF_PATHS_STRV("sysusers.d"), &rf, &pp);
|
||||
r = search_and_fopen(fn, "re", arg_root, (const char**) CONF_PATHS_STRV("sysusers.d"), &rf);
|
||||
if (r < 0) {
|
||||
if (ignore_enoent && r == -ENOENT)
|
||||
return 0;
|
||||
@ -1747,7 +1746,6 @@ static int read_config_file(const char *fn, bool ignore_enoent) {
|
||||
}
|
||||
|
||||
f = rf;
|
||||
fn = pp;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
@ -1999,8 +1997,7 @@ static int run(int argc, char *argv[]) {
|
||||
DISSECT_IMAGE_REQUIRE_ROOT |
|
||||
DISSECT_IMAGE_VALIDATE_OS |
|
||||
DISSECT_IMAGE_RELAX_VAR_CHECK |
|
||||
DISSECT_IMAGE_FSCK |
|
||||
DISSECT_IMAGE_GROWFS,
|
||||
DISSECT_IMAGE_FSCK,
|
||||
&unlink_dir,
|
||||
&loop_device,
|
||||
&decrypted_image);
|
||||
|
||||
@ -24,14 +24,13 @@ static void test_xescape_full(bool eight_bits) {
|
||||
"a\\x62c\\x5c\"\\x08\\x0c\\x0a\\x0d\\x09\\x0b\\x07\\x03\\x7f\\x9c\\xcb" :
|
||||
"a\\x62c\\x5c\"\\x08\\x0c\\x0a\\x0d\\x09\\x0b\\x07\\x03\177\234\313";
|
||||
const unsigned full_fit = !eight_bits ? 55 : 46;
|
||||
XEscapeFlags flags = eight_bits * XESCAPE_8_BIT;
|
||||
|
||||
for (unsigned i = 0; i < 60; i++) {
|
||||
_cleanup_free_ char *t, *q;
|
||||
_cleanup_free_ char *t;
|
||||
|
||||
assert_se(t = xescape_full("abc\\\"\b\f\n\r\t\v\a\003\177\234\313", "b", i, flags));
|
||||
assert_se(t = xescape_full("abc\\\"\b\f\n\r\t\v\a\003\177\234\313", "b", i, eight_bits));
|
||||
|
||||
log_info("%02d: <%s>", i, t);
|
||||
log_info("%02d: %s", i, t);
|
||||
|
||||
if (i >= full_fit)
|
||||
assert_se(streq(t, escaped));
|
||||
@ -45,15 +44,6 @@ static void test_xescape_full(bool eight_bits) {
|
||||
assert_se(strlen(t) == i);
|
||||
assert_se(strneq(t, "...", i));
|
||||
}
|
||||
|
||||
assert_se(q = xescape_full("abc\\\"\b\f\n\r\t\v\a\003\177\234\313", "b", i,
|
||||
flags | XESCAPE_FORCE_ELLIPSIS));
|
||||
|
||||
log_info("%02d: <%s>", i, q);
|
||||
if (i > 0)
|
||||
assert_se(endswith(q, "."));
|
||||
assert(strlen(q) <= i);
|
||||
assert(strlen(q) + 3 >= strlen(t));
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,7 +118,6 @@ static void test_shell_escape_one(const char *s, const char *bad, const char *ex
|
||||
_cleanup_free_ char *r;
|
||||
|
||||
assert_se(r = shell_escape(s, bad));
|
||||
log_debug("%s → %s (expected %s)", s, r, expected);
|
||||
assert_se(streq_ptr(r, expected));
|
||||
}
|
||||
|
||||
@ -138,58 +127,58 @@ static void test_shell_escape(void) {
|
||||
test_shell_escape_one("foobar", "", "foobar");
|
||||
test_shell_escape_one("foobar", "o", "f\\o\\obar");
|
||||
test_shell_escape_one("foo:bar,baz", ",:", "foo\\:bar\\,baz");
|
||||
test_shell_escape_one("foo\nbar\nbaz", ",:", "foo\\nbar\\nbaz");
|
||||
}
|
||||
|
||||
static void test_shell_maybe_quote_one(const char *s, ShellEscapeFlags flags, const char *expected) {
|
||||
static void test_shell_maybe_quote_one(const char *s,
|
||||
EscapeStyle style,
|
||||
const char *expected) {
|
||||
_cleanup_free_ char *ret = NULL;
|
||||
|
||||
assert_se(ret = shell_maybe_quote(s, flags));
|
||||
assert_se(ret = shell_maybe_quote(s, style));
|
||||
log_debug("[%s] → [%s] (%s)", s, ret, expected);
|
||||
assert_se(streq(ret, expected));
|
||||
}
|
||||
|
||||
static void test_shell_maybe_quote(void) {
|
||||
|
||||
test_shell_maybe_quote_one("", 0, "");
|
||||
test_shell_maybe_quote_one("", SHELL_ESCAPE_EMPTY, "\"\"");
|
||||
test_shell_maybe_quote_one("", SHELL_ESCAPE_POSIX, "");
|
||||
test_shell_maybe_quote_one("", SHELL_ESCAPE_POSIX | SHELL_ESCAPE_EMPTY, "\"\"");
|
||||
test_shell_maybe_quote_one("\\", 0, "\"\\\\\"");
|
||||
test_shell_maybe_quote_one("\\", SHELL_ESCAPE_POSIX, "$'\\\\'");
|
||||
test_shell_maybe_quote_one("\"", 0, "\"\\\"\"");
|
||||
test_shell_maybe_quote_one("\"", SHELL_ESCAPE_POSIX, "$'\"'");
|
||||
test_shell_maybe_quote_one("foobar", 0, "foobar");
|
||||
test_shell_maybe_quote_one("foobar", SHELL_ESCAPE_POSIX, "foobar");
|
||||
test_shell_maybe_quote_one("foo bar", 0, "\"foo bar\"");
|
||||
test_shell_maybe_quote_one("foo bar", SHELL_ESCAPE_POSIX, "$'foo bar'");
|
||||
test_shell_maybe_quote_one("foo\tbar", 0, "\"foo\\tbar\"");
|
||||
test_shell_maybe_quote_one("foo\tbar", SHELL_ESCAPE_POSIX, "$'foo\\tbar'");
|
||||
test_shell_maybe_quote_one("foo\nbar", 0, "\"foo\\nbar\"");
|
||||
test_shell_maybe_quote_one("foo\nbar", SHELL_ESCAPE_POSIX, "$'foo\\nbar'");
|
||||
test_shell_maybe_quote_one("foo \"bar\" waldo", 0, "\"foo \\\"bar\\\" waldo\"");
|
||||
test_shell_maybe_quote_one("foo \"bar\" waldo", SHELL_ESCAPE_POSIX, "$'foo \"bar\" waldo'");
|
||||
test_shell_maybe_quote_one("foo$bar", 0, "\"foo\\$bar\"");
|
||||
test_shell_maybe_quote_one("foo$bar", SHELL_ESCAPE_EMPTY, "\"foo\\$bar\"");
|
||||
test_shell_maybe_quote_one("foo$bar", SHELL_ESCAPE_POSIX, "$'foo$bar'");
|
||||
test_shell_maybe_quote_one("foo$bar", SHELL_ESCAPE_POSIX | SHELL_ESCAPE_EMPTY, "$'foo$bar'");
|
||||
test_shell_maybe_quote_one("", ESCAPE_BACKSLASH, "");
|
||||
test_shell_maybe_quote_one("", ESCAPE_BACKSLASH_ONELINE, "");
|
||||
test_shell_maybe_quote_one("", ESCAPE_POSIX, "");
|
||||
test_shell_maybe_quote_one("\\", ESCAPE_BACKSLASH, "\"\\\\\"");
|
||||
test_shell_maybe_quote_one("\\", ESCAPE_BACKSLASH_ONELINE, "\"\\\\\"");
|
||||
test_shell_maybe_quote_one("\\", ESCAPE_POSIX, "$'\\\\'");
|
||||
test_shell_maybe_quote_one("\"", ESCAPE_BACKSLASH, "\"\\\"\"");
|
||||
test_shell_maybe_quote_one("\"", ESCAPE_BACKSLASH_ONELINE, "\"\\\"\"");
|
||||
test_shell_maybe_quote_one("\"", ESCAPE_POSIX, "$'\"'");
|
||||
test_shell_maybe_quote_one("foobar", ESCAPE_BACKSLASH, "foobar");
|
||||
test_shell_maybe_quote_one("foobar", ESCAPE_BACKSLASH_ONELINE, "foobar");
|
||||
test_shell_maybe_quote_one("foobar", ESCAPE_POSIX, "foobar");
|
||||
test_shell_maybe_quote_one("foo bar", ESCAPE_BACKSLASH, "\"foo bar\"");
|
||||
test_shell_maybe_quote_one("foo bar", ESCAPE_BACKSLASH_ONELINE, "\"foo bar\"");
|
||||
test_shell_maybe_quote_one("foo bar", ESCAPE_POSIX, "$'foo bar'");
|
||||
test_shell_maybe_quote_one("foo\tbar", ESCAPE_BACKSLASH, "\"foo\tbar\"");
|
||||
test_shell_maybe_quote_one("foo\tbar", ESCAPE_BACKSLASH_ONELINE, "\"foo\\tbar\"");
|
||||
test_shell_maybe_quote_one("foo\tbar", ESCAPE_POSIX, "$'foo\\tbar'");
|
||||
test_shell_maybe_quote_one("foo\nbar", ESCAPE_BACKSLASH, "\"foo\nbar\"");
|
||||
test_shell_maybe_quote_one("foo\nbar", ESCAPE_BACKSLASH_ONELINE, "\"foo\\nbar\"");
|
||||
test_shell_maybe_quote_one("foo\nbar", ESCAPE_POSIX, "$'foo\\nbar'");
|
||||
test_shell_maybe_quote_one("foo \"bar\" waldo", ESCAPE_BACKSLASH, "\"foo \\\"bar\\\" waldo\"");
|
||||
test_shell_maybe_quote_one("foo \"bar\" waldo", ESCAPE_BACKSLASH_ONELINE, "\"foo \\\"bar\\\" waldo\"");
|
||||
test_shell_maybe_quote_one("foo \"bar\" waldo", ESCAPE_POSIX, "$'foo \"bar\" waldo'");
|
||||
test_shell_maybe_quote_one("foo$bar", ESCAPE_BACKSLASH, "\"foo\\$bar\"");
|
||||
test_shell_maybe_quote_one("foo$bar", ESCAPE_BACKSLASH_ONELINE, "\"foo\\$bar\"");
|
||||
test_shell_maybe_quote_one("foo$bar", ESCAPE_POSIX, "$'foo$bar'");
|
||||
|
||||
/* Exclamation mark is special in the interactive shell, but we don't treat it so. */
|
||||
test_shell_maybe_quote_one("foo!bar", 0, "\"foo!bar\"");
|
||||
test_shell_maybe_quote_one("foo!bar", SHELL_ESCAPE_POSIX, "$'foo!bar'");
|
||||
/* Note that current users disallow control characters, so this "test"
|
||||
* is here merely to establish current behaviour. If control characters
|
||||
* were allowed, they should be quoted, i.e. \001 should become \\001. */
|
||||
test_shell_maybe_quote_one("a\nb\001", ESCAPE_BACKSLASH, "\"a\nb\001\"");
|
||||
test_shell_maybe_quote_one("a\nb\001", ESCAPE_BACKSLASH_ONELINE, "\"a\\nb\001\"");
|
||||
test_shell_maybe_quote_one("a\nb\001", ESCAPE_POSIX, "$'a\\nb\001'");
|
||||
|
||||
/* Control characters and unicode */
|
||||
test_shell_maybe_quote_one("a\nb\001", 0, "\"a\\nb\\001\"");
|
||||
test_shell_maybe_quote_one("a\nb\001", SHELL_ESCAPE_POSIX, "$'a\\nb\\001'");
|
||||
|
||||
test_shell_maybe_quote_one("głąb", 0, "głąb");
|
||||
test_shell_maybe_quote_one("głąb", SHELL_ESCAPE_POSIX, "głąb");
|
||||
|
||||
test_shell_maybe_quote_one("głąb\002\003", 0, "\"głąb\\002\\003\"");
|
||||
test_shell_maybe_quote_one("głąb\002\003", SHELL_ESCAPE_POSIX, "$'głąb\\002\\003'");
|
||||
|
||||
test_shell_maybe_quote_one("głąb\002\003rząd", 0, "\"głąb\\002\\003rząd\"");
|
||||
test_shell_maybe_quote_one("głąb\002\003rząd", SHELL_ESCAPE_POSIX, "$'głąb\\002\\003rząd'");
|
||||
test_shell_maybe_quote_one("foo!bar", ESCAPE_BACKSLASH, "\"foo!bar\"");
|
||||
test_shell_maybe_quote_one("foo!bar", ESCAPE_BACKSLASH_ONELINE, "\"foo!bar\"");
|
||||
test_shell_maybe_quote_one("foo!bar", ESCAPE_POSIX, "$'foo!bar'");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
@ -15,7 +15,6 @@
|
||||
#include "fs-util.h"
|
||||
#include "io-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "random-util.h"
|
||||
#include "rm-rf.h"
|
||||
@ -322,8 +321,6 @@ static void test_executable_is_script(void) {
|
||||
char *command;
|
||||
int r;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
assert_se(fmkostemp_safe(t, "w", &f) == 0);
|
||||
fputs("#! /bin/script -a -b \ngoo goo", f);
|
||||
fflush(f);
|
||||
@ -349,8 +346,6 @@ static void test_status_field(void) {
|
||||
unsigned long long total = 0, buffers = 0;
|
||||
int r;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
assert_se(get_proc_field("/proc/self/status", "Threads", WHITESPACE, &t) == 0);
|
||||
puts(t);
|
||||
assert_se(streq(t, "1"));
|
||||
@ -382,11 +377,11 @@ static void test_status_field(void) {
|
||||
}
|
||||
|
||||
static void test_capeff(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
int pid, p;
|
||||
|
||||
for (int pid = 0; pid < 2; pid++) {
|
||||
for (pid = 0; pid < 2; pid++) {
|
||||
_cleanup_free_ char *capeff = NULL;
|
||||
int r, p;
|
||||
int r;
|
||||
|
||||
r = get_process_capeff(0, &capeff);
|
||||
log_info("capeff: '%s' (r=%d)", capeff, r);
|
||||
@ -407,8 +402,6 @@ static void test_write_string_stream(void) {
|
||||
int fd;
|
||||
char buf[64];
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
fd = mkostemp_safe(fn);
|
||||
assert_se(fd >= 0);
|
||||
|
||||
@ -443,8 +436,6 @@ static void test_write_string_file(void) {
|
||||
char buf[64] = {};
|
||||
_cleanup_close_ int fd;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
fd = mkostemp_safe(fn);
|
||||
assert_se(fd >= 0);
|
||||
|
||||
@ -459,8 +450,6 @@ static void test_write_string_file_no_create(void) {
|
||||
_cleanup_close_ int fd;
|
||||
char buf[64] = {};
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
fd = mkostemp_safe(fn);
|
||||
assert_se(fd >= 0);
|
||||
|
||||
@ -475,8 +464,6 @@ static void test_write_string_file_verify(void) {
|
||||
_cleanup_free_ char *buf = NULL, *buf2 = NULL;
|
||||
int r;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
r = read_one_line_file("/proc/version", &buf);
|
||||
if (ERRNO_IS_PRIVILEGE(r))
|
||||
return;
|
||||
@ -503,8 +490,6 @@ static void test_load_env_file_pairs(void) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
char **k, **v;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
fd = mkostemp_safe(fn);
|
||||
assert_se(fd >= 0);
|
||||
|
||||
@ -540,97 +525,69 @@ static void test_load_env_file_pairs(void) {
|
||||
}
|
||||
|
||||
static void test_search_and_fopen(void) {
|
||||
static const char* const dirs[] = {
|
||||
"/tmp/foo/bar",
|
||||
"/tmp",
|
||||
NULL
|
||||
};
|
||||
char name[] = "/tmp/test-search_and_fopen.XXXXXX";
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
const char *e;
|
||||
int r;
|
||||
const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL};
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
char name[] = "/tmp/test-search_and_fopen.XXXXXX";
|
||||
int fd, r;
|
||||
FILE *f;
|
||||
|
||||
fd = mkostemp_safe(name);
|
||||
assert_se(fd >= 0);
|
||||
fd = safe_close(fd);
|
||||
close(fd);
|
||||
|
||||
r = search_and_fopen(basename(name), "re", NULL, (const char**) dirs, &f, &p);
|
||||
r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
|
||||
assert_se(r >= 0);
|
||||
assert_se(e = path_startswith(p, "/tmp/"));
|
||||
assert_se(streq(basename(name), e));
|
||||
f = safe_fclose(f);
|
||||
p = mfree(p);
|
||||
fclose(f);
|
||||
|
||||
r = search_and_fopen(name, "re", NULL, (const char**) dirs, &f, &p);
|
||||
r = search_and_fopen(name, "r", NULL, dirs, &f);
|
||||
assert_se(r >= 0);
|
||||
assert_se(path_equal(name, p));
|
||||
f = safe_fclose(f);
|
||||
p = mfree(p);
|
||||
fclose(f);
|
||||
|
||||
r = search_and_fopen(basename(name), "re", "/", (const char**) dirs, &f, &p);
|
||||
r = search_and_fopen(basename(name), "r", "/", dirs, &f);
|
||||
assert_se(r >= 0);
|
||||
assert_se(e = path_startswith(p, "/tmp/"));
|
||||
assert_se(streq(basename(name), e));
|
||||
f = safe_fclose(f);
|
||||
p = mfree(p);
|
||||
fclose(f);
|
||||
|
||||
r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, (const char**) dirs, &f, &p);
|
||||
assert_se(r == -ENOENT);
|
||||
r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, (const char**) dirs, &f, &p);
|
||||
assert_se(r == -ENOENT);
|
||||
r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
|
||||
assert_se(r < 0);
|
||||
r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
|
||||
assert_se(r < 0);
|
||||
|
||||
r = unlink(name);
|
||||
assert_se(r == 0);
|
||||
|
||||
r = search_and_fopen(basename(name), "r", NULL, (const char**) dirs, &f, &p);
|
||||
assert_se(r == -ENOENT);
|
||||
r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
|
||||
assert_se(r < 0);
|
||||
}
|
||||
|
||||
static void test_search_and_fopen_nulstr(void) {
|
||||
static const char dirs[] =
|
||||
"/tmp/foo/bar\0"
|
||||
"/tmp\0";
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
const char dirs[] = "/tmp/foo/bar\0/tmp\0";
|
||||
|
||||
_cleanup_(unlink_tempfilep) char name[] = "/tmp/test-search_and_fopen.XXXXXX";
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
const char *e;
|
||||
int r;
|
||||
int fd, r;
|
||||
FILE *f;
|
||||
|
||||
fd = mkostemp_safe(name);
|
||||
assert_se(fd >= 0);
|
||||
fd = safe_close(fd);
|
||||
close(fd);
|
||||
|
||||
r = search_and_fopen_nulstr(basename(name), "re", NULL, dirs, &f, &p);
|
||||
r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
|
||||
assert_se(r >= 0);
|
||||
assert_se(e = path_startswith(p, "/tmp/"));
|
||||
assert_se(streq(basename(name), e));
|
||||
f = safe_fclose(f);
|
||||
p = mfree(p);
|
||||
fclose(f);
|
||||
|
||||
r = search_and_fopen_nulstr(name, "re", NULL, dirs, &f, &p);
|
||||
r = search_and_fopen_nulstr(name, "r", NULL, dirs, &f);
|
||||
assert_se(r >= 0);
|
||||
assert_se(path_equal(name, p));
|
||||
f = safe_fclose(f);
|
||||
p = mfree(p);
|
||||
fclose(f);
|
||||
|
||||
r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f, &p);
|
||||
assert_se(r == -ENOENT);
|
||||
r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f, &p);
|
||||
assert_se(r == -ENOENT);
|
||||
r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
|
||||
assert_se(r < 0);
|
||||
r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
|
||||
assert_se(r < 0);
|
||||
|
||||
r = unlink(name);
|
||||
assert_se(r == 0);
|
||||
|
||||
r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f, &p);
|
||||
assert_se(r == -ENOENT);
|
||||
r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
|
||||
assert_se(r < 0);
|
||||
}
|
||||
|
||||
static void test_writing_tmpfile(void) {
|
||||
@ -638,15 +595,12 @@ static void test_writing_tmpfile(void) {
|
||||
_cleanup_free_ char *contents = NULL;
|
||||
size_t size;
|
||||
_cleanup_close_ int fd = -1;
|
||||
struct iovec iov[3];
|
||||
int r;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
struct iovec iov[] = {
|
||||
IOVEC_MAKE_STRING("abc\n"),
|
||||
IOVEC_MAKE_STRING(ALPHANUMERICAL "\n"),
|
||||
IOVEC_MAKE_STRING(""),
|
||||
};
|
||||
iov[0] = IOVEC_MAKE_STRING("abc\n");
|
||||
iov[1] = IOVEC_MAKE_STRING(ALPHANUMERICAL "\n");
|
||||
iov[2] = IOVEC_MAKE_STRING("");
|
||||
|
||||
fd = mkostemp_safe(name);
|
||||
printf("tmpfile: %s", name);
|
||||
@ -663,8 +617,6 @@ static void test_writing_tmpfile(void) {
|
||||
static void test_tempfn(void) {
|
||||
char *ret = NULL, *p;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
assert_se(tempfn_xxxxxx("/foo/bar/waldo", NULL, &ret) >= 0);
|
||||
assert_se(streq_ptr(ret, "/foo/bar/.#waldoXXXXXX"));
|
||||
free(ret);
|
||||
@ -707,7 +659,8 @@ static void test_fgetc(void) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
char c;
|
||||
|
||||
assert_se(f = fmemopen_unlocked((void*) chars, sizeof(chars), "re"));
|
||||
f = fmemopen_unlocked((void*) chars, sizeof(chars), "re");
|
||||
assert_se(f);
|
||||
|
||||
for (size_t i = 0; i < sizeof(chars); i++) {
|
||||
assert_se(safe_fgetc(f, &c) == 1);
|
||||
@ -800,9 +753,9 @@ static void test_read_line_one_file(FILE *f) {
|
||||
static void test_read_line(void) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
f = fmemopen_unlocked((void*) buffer, sizeof(buffer), "re");
|
||||
assert_se(f);
|
||||
|
||||
assert_se(f = fmemopen_unlocked((void*) buffer, sizeof(buffer), "re"));
|
||||
test_read_line_one_file(f);
|
||||
}
|
||||
|
||||
@ -811,8 +764,6 @@ static void test_read_line2(void) {
|
||||
int fd;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
fd = mkostemp_safe(name);
|
||||
assert_se(fd >= 0);
|
||||
assert_se((size_t) write(fd, buffer, sizeof(buffer)) == sizeof(buffer));
|
||||
@ -828,8 +779,6 @@ static void test_read_line3(void) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
int r;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
f = fopen("/proc/uptime", "re");
|
||||
if (!f && IN_SET(errno, ENOENT, EPERM))
|
||||
return;
|
||||
@ -862,9 +811,10 @@ static void test_read_line4(void) {
|
||||
{ 6, "foo\n\r\0" },
|
||||
};
|
||||
|
||||
size_t i;
|
||||
int r;
|
||||
|
||||
for (size_t i = 0; i < ELEMENTSOF(eof_endings); i++) {
|
||||
for (i = 0; i < ELEMENTSOF(eof_endings); i++) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_free_ char *s = NULL;
|
||||
|
||||
@ -889,8 +839,6 @@ static void test_read_nul_string(void) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_free_ char *s = NULL;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
assert_se(f = fmemopen_unlocked((void*) test, sizeof(test)-1, "r"));
|
||||
|
||||
assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 13 && streq_ptr(s, "string nr. 1"));
|
||||
@ -980,8 +928,6 @@ static void test_read_full_file_offset_size(void) {
|
||||
size_t rbuf_size;
|
||||
uint8_t buf[4711];
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
random_bytes(buf, sizeof(buf));
|
||||
|
||||
assert_se(tempfn_random_child(NULL, NULL, &fn) >= 0);
|
||||
@ -1019,12 +965,10 @@ static void test_read_full_file_offset_size(void) {
|
||||
rbuf = mfree(rbuf);
|
||||
}
|
||||
|
||||
static void test_read_virtual_file(size_t max_size) {
|
||||
static void test_read_full_virtual_file(void) {
|
||||
const char *filename;
|
||||
int r;
|
||||
|
||||
log_info("/* %s (max_size=%zu) */", __func__, max_size);
|
||||
|
||||
FOREACH_STRING(filename,
|
||||
"/proc/1/cmdline",
|
||||
"/etc/nsswitch.conf",
|
||||
@ -1033,8 +977,8 @@ static void test_read_virtual_file(size_t max_size) {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
r = read_virtual_file(filename, max_size, &buf, &size);
|
||||
log_info_errno(r, "read_virtual_file(\"%s\", %zu): %m (%zu bytes)", filename, max_size, size);
|
||||
r = read_full_virtual_file(filename, &buf, &size);
|
||||
log_info_errno(r, "read_full_virtual_file(\"%s\"): %m (%zu bytes)", filename, size);
|
||||
assert_se(r == 0 || ERRNO_IS_PRIVILEGE(r) || r == -ENOENT);
|
||||
}
|
||||
}
|
||||
@ -1066,9 +1010,7 @@ int main(int argc, char *argv[]) {
|
||||
test_read_nul_string();
|
||||
test_read_full_file_socket();
|
||||
test_read_full_file_offset_size();
|
||||
test_read_virtual_file(20);
|
||||
test_read_virtual_file(4096);
|
||||
test_read_virtual_file(SIZE_MAX);
|
||||
test_read_full_virtual_file();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -40,12 +40,5 @@ int main(int argc, char *argv[]) {
|
||||
print_local_addresses(a, (unsigned) n);
|
||||
free(a);
|
||||
|
||||
n = local_outbounds(NULL, 0, AF_UNSPEC, &a);
|
||||
assert_se(n >= 0);
|
||||
|
||||
printf("Local Outbounds:\n");
|
||||
print_local_addresses(a, (unsigned) n);
|
||||
free(a);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -455,7 +455,8 @@ static int parse_argv(int argc, char **argv,
|
||||
} else {
|
||||
_cleanup_free_ char *hostname;
|
||||
assert_se(hostname = gethostname_malloc());
|
||||
assert_se(names = strv_new("localhost", "_gateway", "_outbound", "foo_no_such_host", hostname));
|
||||
|
||||
assert_se(names = strv_new("localhost", "_gateway", "foo_no_such_host", hostname));
|
||||
|
||||
n = make_addresses(&addrs);
|
||||
assert_se(n >= 0);
|
||||
|
||||
@ -15,8 +15,6 @@
|
||||
#include "alloc-util.h"
|
||||
#include "architecture.h"
|
||||
#include "errno-util.h"
|
||||
#include "errno-list.h"
|
||||
#include "dirent-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
@ -45,8 +43,6 @@ static void test_get_process_comm(pid_t pid) {
|
||||
dev_t h;
|
||||
int r;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
xsprintf(path, "/proc/"PID_FMT"/comm", pid);
|
||||
|
||||
if (stat(path, &st) == 0) {
|
||||
@ -92,61 +88,15 @@ static void test_get_process_comm(pid_t pid) {
|
||||
log_info("PID"PID_FMT" $PATH: '%s'", pid, strna(i));
|
||||
}
|
||||
|
||||
static void test_get_process_cmdline_one(pid_t pid) {
|
||||
_cleanup_free_ char *c = NULL, *d = NULL, *e = NULL, *f = NULL, *g = NULL, *h = NULL;
|
||||
int r;
|
||||
|
||||
r = get_process_cmdline(pid, SIZE_MAX, 0, &c);
|
||||
log_info("PID "PID_FMT": %s", pid, r >= 0 ? c : errno_to_name(r));
|
||||
|
||||
r = get_process_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &d);
|
||||
log_info(" %s", r >= 0 ? d : errno_to_name(r));
|
||||
|
||||
r = get_process_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &e);
|
||||
log_info(" %s", r >= 0 ? e : errno_to_name(r));
|
||||
|
||||
r = get_process_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE | PROCESS_CMDLINE_COMM_FALLBACK, &f);
|
||||
log_info(" %s", r >= 0 ? f : errno_to_name(r));
|
||||
|
||||
r = get_process_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &g);
|
||||
log_info(" %s", r >= 0 ? g : errno_to_name(r));
|
||||
|
||||
r = get_process_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX | PROCESS_CMDLINE_COMM_FALLBACK, &h);
|
||||
log_info(" %s", r >= 0 ? h : errno_to_name(r));
|
||||
}
|
||||
|
||||
static void test_get_process_cmdline(void) {
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
struct dirent *de;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
assert_se(d = opendir("/proc"));
|
||||
|
||||
FOREACH_DIRENT(de, d, return) {
|
||||
pid_t pid;
|
||||
|
||||
dirent_ensure_type(d, de);
|
||||
|
||||
if (de->d_type != DT_DIR)
|
||||
continue;
|
||||
|
||||
if (parse_pid(de->d_name, &pid) < 0)
|
||||
continue;
|
||||
|
||||
test_get_process_cmdline_one(pid);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_get_process_comm_escape_one(const char *input, const char *output) {
|
||||
_cleanup_free_ char *n = NULL;
|
||||
|
||||
log_debug("input: <%s> — output: <%s>", input, output);
|
||||
log_info("input: <%s> — output: <%s>", input, output);
|
||||
|
||||
assert_se(prctl(PR_SET_NAME, input) >= 0);
|
||||
assert_se(get_process_comm(0, &n) >= 0);
|
||||
|
||||
log_debug("got: <%s>", n);
|
||||
log_info("got: <%s>", n);
|
||||
|
||||
assert_se(streq_ptr(n, output));
|
||||
}
|
||||
@ -154,8 +104,6 @@ static void test_get_process_comm_escape_one(const char *input, const char *outp
|
||||
static void test_get_process_comm_escape(void) {
|
||||
_cleanup_free_ char *saved = NULL;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
assert_se(get_process_comm(0, &saved) >= 0);
|
||||
|
||||
test_get_process_comm_escape_one("", "");
|
||||
@ -192,8 +140,6 @@ static void test_pid_is_unwaited(void) {
|
||||
static void test_pid_is_alive(void) {
|
||||
pid_t pid;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
pid = fork();
|
||||
assert_se(pid >= 0);
|
||||
if (pid == 0) {
|
||||
@ -209,7 +155,6 @@ static void test_pid_is_alive(void) {
|
||||
}
|
||||
|
||||
static void test_personality(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
assert_se(personality_to_string(PER_LINUX));
|
||||
assert_se(!personality_to_string(PERSONALITY_INVALID));
|
||||
@ -238,8 +183,6 @@ static void test_get_process_cmdline_harder(void) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
pid_t pid;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
if (geteuid() != 0) {
|
||||
log_info("Skipping %s: not root", __func__);
|
||||
return;
|
||||
@ -302,219 +245,151 @@ static void test_get_process_cmdline_harder(void) {
|
||||
|
||||
assert_se(prctl(PR_SET_NAME, "testa") >= 0);
|
||||
|
||||
assert_se(get_process_cmdline(0, SIZE_MAX, 0, &line) == -ENOENT);
|
||||
assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, 0, &line) == -ENOENT);
|
||||
|
||||
assert_se(get_process_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "[testa]"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(streq(line, "\"[testa]\"")); /* quoting is enabled here */
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 0, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 0, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_info("'%s'", line);
|
||||
assert_se(streq(line, ""));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 1, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "…"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 2, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "[…"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 3, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "[t…"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 4, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "[te…"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 5, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "[tes…"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 6, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "[test…"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 7, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "[testa]"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 8, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "[testa]"));
|
||||
line = mfree(line);
|
||||
|
||||
/* Test with multiple arguments that don't require quoting */
|
||||
|
||||
assert_se(write(fd, "foo\0bar", 8) == 8);
|
||||
|
||||
assert_se(get_process_cmdline(0, SIZE_MAX, 0, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, 0, &line) >= 0);
|
||||
log_info("'%s'", line);
|
||||
assert_se(streq(line, "foo bar"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "foo bar"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(write(fd, "quux", 4) == 4);
|
||||
assert_se(get_process_cmdline(0, SIZE_MAX, 0, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, 0, &line) >= 0);
|
||||
log_info("'%s'", line);
|
||||
assert_se(streq(line, "foo bar quux"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "foo bar quux"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 1, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "…"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 2, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "f…"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 3, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "fo…"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 4, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "foo…"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 5, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "foo …"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 6, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "foo b…"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 7, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "foo ba…"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 8, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "foo bar…"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 9, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 9, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "foo bar …"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 10, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "foo bar q…"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 11, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "foo bar qu…"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 12, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "foo bar quux"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 13, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 13, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "foo bar quux"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 14, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 14, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "foo bar quux"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 1000, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 1000, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "foo bar quux"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(ftruncate(fd, 0) >= 0);
|
||||
assert_se(prctl(PR_SET_NAME, "aaaa bbbb cccc") >= 0);
|
||||
|
||||
assert_se(get_process_cmdline(0, SIZE_MAX, 0, &line) == -ENOENT);
|
||||
assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, 0, &line) == -ENOENT);
|
||||
|
||||
assert_se(get_process_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "[aaaa bbbb cccc]"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 10, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "[aaaa bbb…"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 11, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "[aaaa bbbb…"));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
log_debug("'%s'", line);
|
||||
assert_se(get_process_cmdline(getpid_cached(), 12, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
||||
assert_se(streq(line, "[aaaa bbbb …"));
|
||||
line = mfree(line);
|
||||
|
||||
/* Test with multiple arguments that do require quoting */
|
||||
|
||||
#define CMDLINE1 "foo\0'bar'\0\"bar$\"\0x y z\0!``\0"
|
||||
#define EXPECT1 "foo \"'bar'\" \"\\\"bar\\$\\\"\" \"x y z\" \"!\\`\\`\" \"\""
|
||||
#define EXPECT1p "foo $'\\'bar\\'' $'\"bar$\"' $'x y z' $'!``' \"\""
|
||||
assert_se(lseek(fd, SEEK_SET, 0) == 0);
|
||||
assert_se(write(fd, CMDLINE1, sizeof CMDLINE1) == sizeof CMDLINE1);
|
||||
assert_se(ftruncate(fd, sizeof CMDLINE1) == 0);
|
||||
|
||||
assert_se(get_process_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line) >= 0);
|
||||
log_debug("got: ==%s==", line);
|
||||
log_debug("exp: ==%s==", EXPECT1);
|
||||
assert_se(streq(line, EXPECT1));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line) >= 0);
|
||||
log_debug("got: ==%s==", line);
|
||||
log_debug("exp: ==%s==", EXPECT1p);
|
||||
assert_se(streq(line, EXPECT1p));
|
||||
line = mfree(line);
|
||||
|
||||
#define CMDLINE2 "foo\0\1\2\3\0\0"
|
||||
#define EXPECT2 "foo \"\\001\\002\\003\" \"\" \"\""
|
||||
#define EXPECT2p "foo $'\\001\\002\\003' \"\" \"\""
|
||||
assert_se(lseek(fd, SEEK_SET, 0) == 0);
|
||||
assert_se(write(fd, CMDLINE2, sizeof CMDLINE2) == sizeof CMDLINE2);
|
||||
assert_se(ftruncate(fd, sizeof CMDLINE2) == 0);
|
||||
|
||||
assert_se(get_process_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line) >= 0);
|
||||
log_debug("got: ==%s==", line);
|
||||
log_debug("exp: ==%s==", EXPECT2);
|
||||
assert_se(streq(line, EXPECT2));
|
||||
line = mfree(line);
|
||||
|
||||
assert_se(get_process_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line) >= 0);
|
||||
log_debug("got: ==%s==", line);
|
||||
log_debug("exp: ==%s==", EXPECT2p);
|
||||
assert_se(streq(line, EXPECT2p));
|
||||
line = mfree(line);
|
||||
|
||||
safe_close(fd);
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
@ -523,15 +398,11 @@ static void test_rename_process_now(const char *p, int ret) {
|
||||
_cleanup_free_ char *comm = NULL, *cmdline = NULL;
|
||||
int r;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
r = rename_process(p);
|
||||
assert_se(r == ret ||
|
||||
(ret == 0 && r >= 0) ||
|
||||
(ret > 0 && r > 0));
|
||||
|
||||
log_debug_errno(r, "rename_process(%s): %m", p);
|
||||
|
||||
if (r < 0)
|
||||
return;
|
||||
|
||||
@ -542,7 +413,7 @@ static void test_rename_process_now(const char *p, int ret) {
|
||||
#endif
|
||||
|
||||
assert_se(get_process_comm(0, &comm) >= 0);
|
||||
log_debug("comm = <%s>", comm);
|
||||
log_info("comm = <%s>", comm);
|
||||
assert_se(strneq(comm, p, TASK_COMM_LEN-1));
|
||||
/* We expect comm to be at most 16 bytes (TASK_COMM_LEN). The kernel may raise this limit in the
|
||||
* future. We'd only check the initial part, at least until we recompile, but this will still pass. */
|
||||
@ -554,12 +425,9 @@ static void test_rename_process_now(const char *p, int ret) {
|
||||
if (r == 0 && detect_container() > 0)
|
||||
log_info("cmdline = <%s> (not verified, Running in unprivileged container?)", cmdline);
|
||||
else {
|
||||
log_info("cmdline = <%s> (expected <%.*s>)", cmdline, (int) strlen("test-process-util"), p);
|
||||
|
||||
bool skip = cmdline[0] == '"'; /* A shortcut to check if the string is quoted */
|
||||
|
||||
assert_se(strneq(cmdline + skip, p, strlen("test-process-util")));
|
||||
assert_se(startswith(cmdline + skip, p));
|
||||
log_info("cmdline = <%s>", cmdline);
|
||||
assert_se(strneq(p, cmdline, STRLEN("test-process-util")));
|
||||
assert_se(startswith(p, cmdline));
|
||||
}
|
||||
} else
|
||||
log_info("cmdline = <%s> (not verified)", cmdline);
|
||||
@ -569,8 +437,6 @@ static void test_rename_process_one(const char *p, int ret) {
|
||||
siginfo_t si;
|
||||
pid_t pid;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
pid = fork();
|
||||
assert_se(pid >= 0);
|
||||
|
||||
@ -625,8 +491,6 @@ static void test_getpid_cached(void) {
|
||||
siginfo_t si;
|
||||
pid_t a, b, c, d, e, f, child;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
a = raw_getpid();
|
||||
b = getpid_cached();
|
||||
c = getpid();
|
||||
@ -657,28 +521,25 @@ static void test_getpid_cached(void) {
|
||||
assert_se(si.si_code == CLD_EXITED);
|
||||
}
|
||||
|
||||
#define MEASURE_ITERATIONS (10000000LLU)
|
||||
|
||||
static void test_getpid_measure(void) {
|
||||
unsigned long long i;
|
||||
usec_t t, q;
|
||||
|
||||
unsigned long long iterations = slow_tests_enabled() ? 1000000 : 1000;
|
||||
|
||||
log_info("/* %s (%llu iterations) */", __func__, iterations);
|
||||
|
||||
t = now(CLOCK_MONOTONIC);
|
||||
for (unsigned long long i = 0; i < iterations; i++)
|
||||
for (i = 0; i < MEASURE_ITERATIONS; i++)
|
||||
(void) getpid();
|
||||
q = now(CLOCK_MONOTONIC) - t;
|
||||
|
||||
log_info(" glibc getpid(): %lf µs each\n", (double) q / iterations);
|
||||
|
||||
iterations *= 50; /* _cached() is about 50 times faster, so we need more iterations */
|
||||
log_info(" glibc getpid(): %lf µs each\n", (double) q / MEASURE_ITERATIONS);
|
||||
|
||||
t = now(CLOCK_MONOTONIC);
|
||||
for (unsigned long long i = 0; i < iterations; i++)
|
||||
for (i = 0; i < MEASURE_ITERATIONS; i++)
|
||||
(void) getpid_cached();
|
||||
q = now(CLOCK_MONOTONIC) - t;
|
||||
|
||||
log_info("getpid_cached(): %lf µs each\n", (double) q / iterations);
|
||||
log_info("getpid_cached(): %lf µs each\n", (double) q / MEASURE_ITERATIONS);
|
||||
}
|
||||
|
||||
static void test_safe_fork(void) {
|
||||
@ -686,8 +547,6 @@ static void test_safe_fork(void) {
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
BLOCK_SIGNALS(SIGCHLD);
|
||||
|
||||
r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_NULL_STDIO|FORK_REOPEN_LOG, &pid);
|
||||
@ -736,8 +595,6 @@ static void test_ioprio_class_from_to_string_one(const char *val, int expected)
|
||||
}
|
||||
|
||||
static void test_ioprio_class_from_to_string(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
test_ioprio_class_from_to_string_one("none", IOPRIO_CLASS_NONE);
|
||||
test_ioprio_class_from_to_string_one("realtime", IOPRIO_CLASS_RT);
|
||||
test_ioprio_class_from_to_string_one("best-effort", IOPRIO_CLASS_BE);
|
||||
@ -753,10 +610,7 @@ static void test_ioprio_class_from_to_string(void) {
|
||||
static void test_setpriority_closest(void) {
|
||||
int r;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
r = safe_fork("(test-setprio)",
|
||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_WAIT|FORK_LOG, NULL);
|
||||
r = safe_fork("(test-setprio)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_WAIT|FORK_LOG, NULL);
|
||||
assert_se(r >= 0);
|
||||
|
||||
if (r == 0) {
|
||||
@ -840,8 +694,7 @@ static void test_setpriority_closest(void) {
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
log_show_color(true);
|
||||
test_setup_logging(LOG_INFO);
|
||||
test_setup_logging(LOG_DEBUG);
|
||||
|
||||
save_argc_argv(argc, argv);
|
||||
|
||||
@ -856,7 +709,6 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
test_get_process_comm_escape();
|
||||
test_get_process_cmdline();
|
||||
test_pid_is_unwaited();
|
||||
test_pid_is_alive();
|
||||
test_personality();
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
#include "alloc-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "tests.h"
|
||||
#include "utf8.h"
|
||||
#include "util.h"
|
||||
|
||||
@ -92,15 +91,15 @@ static void test_utf8_escape_invalid(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
p1 = utf8_escape_invalid("goo goo goo");
|
||||
log_debug("\"%s\"", p1);
|
||||
puts(p1);
|
||||
assert_se(utf8_is_valid(p1));
|
||||
|
||||
p2 = utf8_escape_invalid("\341\204\341\204");
|
||||
log_debug("\"%s\"", p2);
|
||||
puts(p2);
|
||||
assert_se(utf8_is_valid(p2));
|
||||
|
||||
p3 = utf8_escape_invalid("\341\204");
|
||||
log_debug("\"%s\"", p3);
|
||||
puts(p3);
|
||||
assert_se(utf8_is_valid(p3));
|
||||
}
|
||||
|
||||
@ -110,55 +109,58 @@ static void test_utf8_escape_non_printable(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
p1 = utf8_escape_non_printable("goo goo goo");
|
||||
log_debug("\"%s\"", p1);
|
||||
puts(p1);
|
||||
assert_se(utf8_is_valid(p1));
|
||||
|
||||
p2 = utf8_escape_non_printable("\341\204\341\204");
|
||||
log_debug("\"%s\"", p2);
|
||||
puts(p2);
|
||||
assert_se(utf8_is_valid(p2));
|
||||
|
||||
p3 = utf8_escape_non_printable("\341\204");
|
||||
log_debug("\"%s\"", p3);
|
||||
puts(p3);
|
||||
assert_se(utf8_is_valid(p3));
|
||||
|
||||
p4 = utf8_escape_non_printable("ąę\n가너도루\n1234\n\341\204\341\204\n\001 \019\20\a");
|
||||
log_debug("\"%s\"", p4);
|
||||
puts(p4);
|
||||
assert_se(utf8_is_valid(p4));
|
||||
|
||||
p5 = utf8_escape_non_printable("\001 \019\20\a");
|
||||
log_debug("\"%s\"", p5);
|
||||
puts(p5);
|
||||
assert_se(utf8_is_valid(p5));
|
||||
|
||||
p6 = utf8_escape_non_printable("\xef\xbf\x30\x13");
|
||||
log_debug("\"%s\"", p6);
|
||||
puts(p6);
|
||||
assert_se(utf8_is_valid(p6));
|
||||
}
|
||||
|
||||
static void test_utf8_escape_non_printable_full(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
const char *s;
|
||||
FOREACH_STRING(s,
|
||||
"goo goo goo", /* ASCII */
|
||||
"\001 \019\20\a", /* control characters */
|
||||
"\xef\xbf\x30\x13") /* misplaced continuation bytes followed by a digit and cc */
|
||||
for (size_t cw = 0; cw < 22; cw++) {
|
||||
_cleanup_free_ char *p, *q;
|
||||
size_t ew;
|
||||
for (size_t i = 0; i < 20; i++) {
|
||||
_cleanup_free_ char *p;
|
||||
|
||||
p = utf8_escape_non_printable_full(s, cw, false);
|
||||
ew = utf8_console_width(p);
|
||||
log_debug("%02zu \"%s\" (%zu wasted)", cw, p, cw - ew);
|
||||
p = utf8_escape_non_printable_full("goo goo goo", i);
|
||||
puts(p);
|
||||
assert_se(utf8_is_valid(p));
|
||||
assert_se(ew <= cw);
|
||||
assert_se(utf8_console_width(p) <= i);
|
||||
}
|
||||
|
||||
q = utf8_escape_non_printable_full(s, cw, true);
|
||||
ew = utf8_console_width(q);
|
||||
log_debug(" \"%s\" (%zu wasted)", q, cw - ew);
|
||||
assert_se(utf8_is_valid(q));
|
||||
assert_se(ew <= cw);
|
||||
if (cw > 0)
|
||||
assert_se(endswith(q, "…"));
|
||||
for (size_t i = 0; i < 20; i++) {
|
||||
_cleanup_free_ char *p;
|
||||
|
||||
p = utf8_escape_non_printable_full("\001 \019\20\a", i);
|
||||
puts(p);
|
||||
assert_se(utf8_is_valid(p));
|
||||
assert_se(utf8_console_width(p) <= i);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 20; i++) {
|
||||
_cleanup_free_ char *p;
|
||||
|
||||
p = utf8_escape_non_printable_full("\xef\xbf\x30\x13", i);
|
||||
puts(p);
|
||||
assert_se(utf8_is_valid(p));
|
||||
assert_se(utf8_console_width(p) <= i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -233,9 +235,6 @@ static void test_utf8_to_utf16(void) {
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
log_show_color(true);
|
||||
test_setup_logging(LOG_INFO);
|
||||
|
||||
test_utf8_n_is_valid();
|
||||
test_utf8_is_valid();
|
||||
test_utf8_is_printable();
|
||||
|
||||
@ -3185,7 +3185,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoent, bool *invalid_config) {
|
||||
_cleanup_(hashmap_freep) Hashmap *uid_cache = NULL, *gid_cache = NULL;
|
||||
_cleanup_fclose_ FILE *_f = NULL;
|
||||
_cleanup_free_ char *pp = NULL;
|
||||
unsigned v = 0;
|
||||
FILE *f;
|
||||
ItemArray *ia;
|
||||
@ -3198,7 +3197,7 @@ static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoe
|
||||
fn = "<stdin>";
|
||||
f = stdin;
|
||||
} else {
|
||||
r = search_and_fopen(fn, "re", arg_root, (const char**) config_dirs, &_f, &pp);
|
||||
r = search_and_fopen(fn, "re", arg_root, (const char**) config_dirs, &_f);
|
||||
if (r < 0) {
|
||||
if (ignore_enoent && r == -ENOENT) {
|
||||
log_debug_errno(r, "Failed to open \"%s\", ignoring: %m", fn);
|
||||
@ -3207,9 +3206,7 @@ static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoe
|
||||
|
||||
return log_error_errno(r, "Failed to open '%s': %m", fn);
|
||||
}
|
||||
|
||||
log_debug("Reading config file \"%s\"…", pp);
|
||||
fn = pp;
|
||||
log_debug("Reading config file \"%s\"…", fn);
|
||||
f = _f;
|
||||
}
|
||||
|
||||
@ -3449,8 +3446,7 @@ static int run(int argc, char *argv[]) {
|
||||
DISSECT_IMAGE_REQUIRE_ROOT |
|
||||
DISSECT_IMAGE_VALIDATE_OS |
|
||||
DISSECT_IMAGE_RELAX_VAR_CHECK |
|
||||
DISSECT_IMAGE_FSCK |
|
||||
DISSECT_IMAGE_GROWFS,
|
||||
DISSECT_IMAGE_FSCK,
|
||||
&unlink_dir,
|
||||
&loop_device,
|
||||
&decrypted_image);
|
||||
|
||||
@ -267,7 +267,7 @@ int manager_startup(Manager *m) {
|
||||
else {
|
||||
union sockaddr_union sockaddr = {
|
||||
.un.sun_family = AF_UNIX,
|
||||
.un.sun_path = "/run/systemd/userdb/io.systemd.Multiplexer",
|
||||
.un.sun_path = "/run/systemd/userdb/io.systemd.NameServiceSwitch",
|
||||
};
|
||||
|
||||
r = mkdir_p("/run/systemd/userdb", 0755);
|
||||
@ -284,8 +284,7 @@ int manager_startup(Manager *m) {
|
||||
if (bind(m->listen_fd, &sockaddr.sa, SOCKADDR_UN_LEN(sockaddr.un)) < 0)
|
||||
return log_error_errno(errno, "Failed to bind socket: %m");
|
||||
|
||||
r = symlink_idempotent("io.systemd.Multiplexer",
|
||||
"/run/systemd/userdb/io.systemd.NameServiceSwitch", false);
|
||||
r = symlink_idempotent("io.systemd.NameServiceSwitch", "/run/systemd/userdb/io.systemd.Multiplexer", false);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to bind io.systemd.Multiplexer: %m");
|
||||
|
||||
|
||||
@ -130,8 +130,8 @@ losetup -d "${loop}"
|
||||
ROOT_UUID="$(systemd-id128 -u show "$(head -c 32 "${image}.roothash")" -u | tail -n 1 | cut -b 6-)"
|
||||
VERITY_UUID="$(systemd-id128 -u show "$(tail -c 32 "${image}.roothash")" -u | tail -n 1 | cut -b 6-)"
|
||||
|
||||
systemd-dissect --json=short --root-hash "${roothash}" "${image}.gpt" | grep -q '{"rw":"ro","designator":"root","partition_uuid":"'"$ROOT_UUID"'","partition_label":"Root Partition","fstype":"squashfs","architecture":"'"$architecture"'","verity":"yes",'
|
||||
systemd-dissect --json=short --root-hash "${roothash}" "${image}.gpt" | grep -q '{"rw":"ro","designator":"root-verity","partition_uuid":"'"$VERITY_UUID"'","partition_label":"Verity Partition","fstype":"DM_verity_hash","architecture":"'"$architecture"'","verity":null,'
|
||||
systemd-dissect --json=short --root-hash "${roothash}" "${image}.gpt" | grep -q '{"rw":"ro","designator":"root","partition_uuid":"'"$ROOT_UUID"'","partition_label":"Root Partition","fstype":"squashfs","architecture":"'"$architecture"'","verity":"yes","node":'
|
||||
systemd-dissect --json=short --root-hash "${roothash}" "${image}.gpt" | grep -q '{"rw":"ro","designator":"root-verity","partition_uuid":"'"$VERITY_UUID"'","partition_label":"Verity Partition","fstype":"DM_verity_hash","architecture":"'"$architecture"'","verity":null,"node":'
|
||||
systemd-dissect --root-hash "${roothash}" "${image}.gpt" | grep -q -F "MARKER=1"
|
||||
systemd-dissect --root-hash "${roothash}" "${image}.gpt" | grep -q -F -f <(sed 's/"//g' "$os_release")
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user