mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
Merge pull request #30380 from keszybz/tmpfiles-dry-run
Make tmpfiles/sysusers nicer with local files and implement tmpfiles --dry-run
This commit is contained in:
commit
c9cdbaed17
3
TODO
3
TODO
@ -2457,18 +2457,17 @@ Features:
|
||||
* support crash reporting operation modes (https://live.gnome.org/GnomeOS/Design/Whiteboards/ProblemReporting)
|
||||
|
||||
* tmpfiles:
|
||||
- apply "x" on "D" too (see patch from William Douglas)
|
||||
- allow time-based cleanup in r and R too
|
||||
- instead of ignoring unknown fields, reject them.
|
||||
- creating new directories/subvolumes/fifos/device nodes
|
||||
should not follow symlinks. None of the other adjustment or creation
|
||||
calls follow symlinks.
|
||||
- add --test mode
|
||||
- teach tmpfiles.d q/Q logic something sensible in the context of XFS/ext4
|
||||
project quota
|
||||
- teach tmpfiles.d m/M to move / atomic move + symlink old -> new
|
||||
- add new line type for setting btrfs subvolume attributes (i.e. rw/ro)
|
||||
- tmpfiles: add new line type for setting fcaps
|
||||
- add -n as shortcut for --dry-run in tmpfiles & sysusers & possibly other places
|
||||
|
||||
* udev-link-config:
|
||||
- Make sure ID_PATH is always exported and complete for
|
||||
|
@ -352,10 +352,10 @@
|
||||
|
||||
<para>When this option is used the original file descriptors <command>systemd-run</command> receives are passed
|
||||
to the service processes as-is. If the service runs with different privileges than
|
||||
<command>systemd-run</command>, this means the service might not be able to re-open the passed file
|
||||
<command>systemd-run</command>, this means the service might not be able to reopen the passed file
|
||||
descriptors, due to normal file descriptor access restrictions. If the invoked process is a shell script that
|
||||
uses the <command>echo "hello" >/dev/stderr</command> construct for writing messages to stderr, this might
|
||||
cause problems, as this only works if stderr can be re-opened. To mitigate this use the construct <command>echo
|
||||
cause problems, as this only works if stderr can be reopened. To mitigate this use the construct <command>echo
|
||||
"hello" >&2</command> instead, which is mostly equivalent and avoids this pitfall.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v235"/></listitem>
|
||||
|
@ -40,17 +40,17 @@
|
||||
<citerefentry><refentrytitle>sysusers.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
</para>
|
||||
|
||||
<para>If invoked with no arguments, it applies all directives from all files found in the directories
|
||||
<para>If invoked with no arguments, directives from the configuration files found in the directories
|
||||
specified by
|
||||
<citerefentry><refentrytitle>sysusers.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>. When
|
||||
invoked with positional arguments, if option <option>--replace=<replaceable>PATH</replaceable></option>
|
||||
is specified, arguments specified on the command line are used instead of the configuration file
|
||||
<replaceable>PATH</replaceable>. Otherwise, just the configuration specified by the command line
|
||||
arguments is executed. The string <literal>-</literal> may be specified instead of a filename to instruct
|
||||
<command>systemd-sysusers</command> to read the configuration from standard input. If the argument is a
|
||||
relative path, all configuration directories are searched for a matching file and the file found that has
|
||||
the highest priority is executed. If the argument is an absolute path, that file is used directly without
|
||||
searching of the configuration directories.</para>
|
||||
arguments is executed. If the string <literal>-</literal> is specified instead of a filename, the
|
||||
configuration is read from standard input. If the argument is a file name (without any slashes), all
|
||||
configuration directories are searched for a matching file and the file found that has the highest
|
||||
priority is executed. If the argument is a path, that file is used directly without searching the
|
||||
configuration directories for any other matching file.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
@ -23,8 +23,7 @@
|
||||
<refname>systemd-tmpfiles-setup-dev.service</refname>
|
||||
<refname>systemd-tmpfiles-clean.service</refname>
|
||||
<refname>systemd-tmpfiles-clean.timer</refname>
|
||||
<refpurpose>Creates, deletes and cleans up volatile
|
||||
and temporary files and directories</refpurpose>
|
||||
<refpurpose>Create, delete, and clean up files and directories</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
@ -59,17 +58,20 @@
|
||||
<para><command>systemd-tmpfiles</command> creates, deletes, and cleans up volatile and temporary files
|
||||
and directories, using the configuration file format and location specified in
|
||||
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>. It must
|
||||
be invoked with one or more options <option>--create</option>, <option>--remove</option>, and
|
||||
be invoked with one or more commands <option>--create</option>, <option>--remove</option>, and
|
||||
<option>--clean</option>, to select the respective subset of operations.</para>
|
||||
|
||||
<para>By default, directives from all configuration files are applied. When invoked with
|
||||
<option>--replace=<replaceable>PATH</replaceable></option>, arguments specified on the command line are
|
||||
used instead of the configuration file <replaceable>PATH</replaceable>. Otherwise, if one or more
|
||||
absolute filenames are passed on the command line, only the directives in these files are applied. If
|
||||
<literal>-</literal> is specified instead of a filename, directives are read from standard input. If only
|
||||
the basename of a configuration file is specified, all configuration directories as specified in
|
||||
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> are
|
||||
searched for a matching file and the file found that has the highest priority is executed.</para>
|
||||
<para>If invoked with no arguments, directives from the configuration files found in the directories
|
||||
specified by
|
||||
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>. When
|
||||
invoked with positional arguments, if option <option>--replace=<replaceable>PATH</replaceable></option>
|
||||
is specified, arguments specified on the command line are used instead of the configuration file
|
||||
<replaceable>PATH</replaceable>. Otherwise, just the configuration specified by the command line
|
||||
arguments is executed. If the string <literal>-</literal> is specified instead of a filename, the
|
||||
configuration is read from standard input. If the argument is a file name (without any slashes), all
|
||||
configuration directories are searched for a matching file and the file found that has the highest
|
||||
priority is executed. If the argument is a path, that file is used directly without searching the
|
||||
configuration directories for any other matching file.</para>
|
||||
|
||||
<para>System services (<filename>systemd-tmpfiles-setup.service</filename>,
|
||||
<filename>systemd-tmpfiles-setup-dev-early.service</filename>,
|
||||
@ -96,14 +98,14 @@
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Options</title>
|
||||
<title>Commands and options</title>
|
||||
|
||||
<para>The following options are understood:</para>
|
||||
<para>The following commands are understood:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>--create</option></term>
|
||||
<listitem><para>If this option is passed, all files and
|
||||
<listitem><para>If this command is passed, all files and
|
||||
directories marked with
|
||||
<varname>f</varname>,
|
||||
<varname>F</varname>,
|
||||
@ -129,14 +131,14 @@
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--clean</option></term>
|
||||
<listitem><para>If this option is passed, all files and
|
||||
<listitem><para>If this command is passed, all files and
|
||||
directories with an age parameter configured will be cleaned
|
||||
up.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--remove</option></term>
|
||||
<listitem><para>If this option is passed, the contents of
|
||||
<listitem><para>If this command is passed, the contents of
|
||||
directories marked with <varname>D</varname> or
|
||||
<varname>R</varname>, and files or directories themselves
|
||||
marked with <varname>r</varname> or <varname>R</varname> are
|
||||
@ -179,6 +181,14 @@
|
||||
<xi:include href="version-info.xml" xpointer="v254"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--dry-run</option></term>
|
||||
<listitem><para>Process the configuration and print what operations would be performed, but don't
|
||||
actually change anything in the file system.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--prefix=<replaceable>path</replaceable></option></term>
|
||||
<listitem><para>Only apply rules with paths that start with
|
||||
|
@ -3017,7 +3017,7 @@ SystemCallErrorNumber=EPERM</programlisting>
|
||||
the kernel log buffer, the unit will implicitly gain a dependency of type <varname>After=</varname>
|
||||
on <filename>systemd-journald.socket</filename> (also see the "Implicit Dependencies" section
|
||||
above). Also note that in this case stdout (or stderr, see below) will be an
|
||||
<constant>AF_UNIX</constant> stream socket, and not a pipe or FIFO that can be re-opened. This means
|
||||
<constant>AF_UNIX</constant> stream socket, and not a pipe or FIFO that can be reopened. This means
|
||||
when executing shell scripts the construct <command>echo "hello" > /dev/stderr</command> for
|
||||
writing text to stderr will not work. To mitigate this use the construct <command>echo "hello"
|
||||
>&2</command> instead, which is mostly equivalent and avoids this pitfall.</para>
|
||||
|
@ -353,9 +353,7 @@ L /tmp/foobar - - - - /dev/null</programlisting>
|
||||
<term><varname>x</varname></term>
|
||||
<listitem><para>Ignore a path during cleaning. Use this type
|
||||
to exclude paths from clean-up as controlled with the Age
|
||||
parameter. Note that lines of this type do not influence the
|
||||
effect of <varname>r</varname> or <varname>R</varname>
|
||||
lines. Lines of this type accept shell-style globs in place
|
||||
parameter. Lines of this type accept shell-style globs in place
|
||||
of normal path names. </para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
@ -365,9 +363,7 @@ L /tmp/foobar - - - - /dev/null</programlisting>
|
||||
to exclude paths from clean-up as controlled with the Age
|
||||
parameter. Unlike <varname>x</varname>, this parameter will
|
||||
not exclude the content if path is a directory, but only
|
||||
directory itself. Note that lines of this type do not
|
||||
influence the effect of <varname>r</varname> or
|
||||
<varname>R</varname> lines. Lines of this type accept
|
||||
directory itself. Lines of this type accept
|
||||
shell-style globs in place of normal path names.
|
||||
</para>
|
||||
|
||||
|
@ -9,7 +9,10 @@
|
||||
#include "conf-files.h"
|
||||
#include "constants.h"
|
||||
#include "dirent-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "glyph-util.h"
|
||||
#include "hashmap.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
@ -372,3 +375,97 @@ int conf_files_list_dropins(
|
||||
|
||||
return conf_files_list_strv(ret, ".conf", root, 0, (const char* const*) dropin_dirs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open and read a config file.
|
||||
*
|
||||
* The <fn> argument may be:
|
||||
* - '-', meaning stdin.
|
||||
* - a file name without a path. In this case <config_dirs> are searched.
|
||||
* - a path, either relative or absolute. In this case <fn> is opened directly.
|
||||
*
|
||||
* This method is only suitable for configuration files which have a flat layout without dropins.
|
||||
*/
|
||||
int conf_file_read(
|
||||
const char *root,
|
||||
const char **config_dirs,
|
||||
const char *fn,
|
||||
parse_line_t parse_line,
|
||||
void *userdata,
|
||||
bool ignore_enoent,
|
||||
bool *invalid_config) {
|
||||
|
||||
_cleanup_fclose_ FILE *_f = NULL;
|
||||
_cleanup_free_ char *_fn = NULL;
|
||||
unsigned v = 0;
|
||||
FILE *f;
|
||||
int r = 0;
|
||||
|
||||
assert(fn);
|
||||
|
||||
if (streq(fn, "-")) {
|
||||
f = stdin;
|
||||
fn = "<stdin>";
|
||||
|
||||
log_debug("Reading config from stdin%s", special_glyph(SPECIAL_GLYPH_ELLIPSIS));
|
||||
|
||||
} else if (is_path(fn)) {
|
||||
r = path_make_absolute_cwd(fn, &_fn);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to make path absolute: %m");
|
||||
fn = _fn;
|
||||
|
||||
f = _f = fopen(fn, "re");
|
||||
if (!_f)
|
||||
r = -errno;
|
||||
else
|
||||
log_debug("Reading config file \"%s\"%s", fn, special_glyph(SPECIAL_GLYPH_ELLIPSIS));
|
||||
|
||||
} else {
|
||||
r = search_and_fopen(fn, "re", root, config_dirs, &_f, &_fn);
|
||||
if (r >= 0) {
|
||||
f = _f;
|
||||
fn = _fn;
|
||||
log_debug("Reading config file \"%s\"%s", fn, special_glyph(SPECIAL_GLYPH_ELLIPSIS));
|
||||
}
|
||||
}
|
||||
|
||||
if (r == -ENOENT && ignore_enoent) {
|
||||
log_debug_errno(r, "Failed to open \"%s\", ignoring: %m", fn);
|
||||
return 0; /* No error, but nothing happened. */
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read '%s': %m", fn);
|
||||
|
||||
r = 1; /* We entered the part where we may modify state. */
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
bool invalid_line = false;
|
||||
int k;
|
||||
|
||||
k = read_stripped_line(f, LONG_LINE_MAX, &line);
|
||||
if (k < 0)
|
||||
return log_error_errno(k, "Failed to read '%s': %m", fn);
|
||||
if (k == 0)
|
||||
break;
|
||||
|
||||
v++;
|
||||
|
||||
if (IN_SET(line[0], 0, '#'))
|
||||
continue;
|
||||
|
||||
k = parse_line(fn, v, line, invalid_config ? &invalid_line : NULL, userdata);
|
||||
if (k < 0 && invalid_line)
|
||||
/* Allow reporting with a special code if the caller requested this. */
|
||||
*invalid_config = true;
|
||||
else
|
||||
/* The first error, if any, becomes our return value. */
|
||||
RET_GATHER(r, k);
|
||||
}
|
||||
|
||||
if (ferror(f))
|
||||
RET_GATHER(r, log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to read from file %s.", fn));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "macro.h"
|
||||
|
||||
enum {
|
||||
@ -29,3 +31,19 @@ int conf_files_list_dropins(
|
||||
const char *dropin_dirname,
|
||||
const char *root,
|
||||
const char * const *dirs);
|
||||
|
||||
typedef int parse_line_t(
|
||||
const char *fname,
|
||||
unsigned line,
|
||||
const char *buffer,
|
||||
bool *invalid_config,
|
||||
void *userdata);
|
||||
|
||||
int conf_file_read(
|
||||
const char *root,
|
||||
const char **config_dirs,
|
||||
const char *fn,
|
||||
parse_line_t parse_line,
|
||||
void *userdata,
|
||||
bool ignore_enoent,
|
||||
bool *invalid_config);
|
||||
|
@ -303,7 +303,7 @@ EFI_STATUS chunked_read(EFI_FILE *file, size_t *size, void *buf) {
|
||||
* Some broken firmwares cannot handle large file reads and will instead return
|
||||
* an error. As a workaround, read such files in small chunks.
|
||||
* Note that we cannot just try reading the whole file first on such firmware as
|
||||
* that will permanently break the handle even if it is re-opened.
|
||||
* that will permanently break the handle even if it is reopened.
|
||||
*
|
||||
* https://github.com/systemd/systemd/issues/25911 */
|
||||
|
||||
|
@ -502,7 +502,7 @@ static void test_sequence_numbers_one(void) {
|
||||
test_close(one);
|
||||
|
||||
/* If the machine-id is not initialized, the header file verification
|
||||
* (which happens when re-opening a journal file) will fail. */
|
||||
* (which happens when reopening a journal file) will fail. */
|
||||
if (sd_id128_get_machine(NULL) >= 0) {
|
||||
/* restart server */
|
||||
seqnum = 0;
|
||||
|
@ -270,7 +270,7 @@ int inhibitor_load(Inhibitor *i) {
|
||||
if (i->fifo_path) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
|
||||
/* Let's re-open the FIFO on both sides, and close the writing side right away */
|
||||
/* Let's reopen the FIFO on both sides, and close the writing side right away */
|
||||
fd = inhibitor_create_fifo(i);
|
||||
if (fd < 0)
|
||||
return log_error_errno(fd, "Failed to reopen FIFO: %m");
|
||||
|
@ -760,7 +760,7 @@ int pty_forward_new(
|
||||
else {
|
||||
/* If we shall be invoked in interactive mode, let's switch on non-blocking mode, so that we
|
||||
* never end up staving one direction while we block on the other. However, let's be careful
|
||||
* here and not turn on O_NONBLOCK for stdin/stdout directly, but of re-opened copies of
|
||||
* here and not turn on O_NONBLOCK for stdin/stdout directly, but of reopened copies of
|
||||
* them. This has two advantages: when we are killed abruptly the stdin/stdout fds won't be
|
||||
* left in O_NONBLOCK state for the next process using them. In addition, if some process
|
||||
* running in the background wants to continue writing to our stdout it can do so without
|
||||
|
@ -1680,11 +1680,13 @@ static int item_equivalent(Item *a, Item *b) {
|
||||
}
|
||||
|
||||
static int parse_line(
|
||||
Context *c,
|
||||
const char *fname,
|
||||
unsigned line,
|
||||
const char *buffer) {
|
||||
const char *buffer,
|
||||
bool *invalid_config,
|
||||
void *context) {
|
||||
|
||||
Context *c = ASSERT_PTR(context);
|
||||
_cleanup_free_ char *action = NULL,
|
||||
*name = NULL, *resolved_name = NULL,
|
||||
*id = NULL, *resolved_id = NULL,
|
||||
@ -1697,10 +1699,10 @@ static int parse_line(
|
||||
int r;
|
||||
const char *p;
|
||||
|
||||
assert(c);
|
||||
assert(fname);
|
||||
assert(line >= 1);
|
||||
assert(buffer);
|
||||
assert(!invalid_config); /* We don't support invalid_config yet. */
|
||||
|
||||
/* Parse columns */
|
||||
p = buffer;
|
||||
@ -1969,57 +1971,14 @@ static int parse_line(
|
||||
}
|
||||
|
||||
static int read_config_file(Context *c, 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;
|
||||
|
||||
assert(c);
|
||||
assert(fn);
|
||||
|
||||
if (streq(fn, "-"))
|
||||
f = stdin;
|
||||
else {
|
||||
r = search_and_fopen(fn, "re", arg_root, (const char**) CONF_PATHS_STRV("sysusers.d"), &rf, &pp);
|
||||
if (r < 0) {
|
||||
if (ignore_enoent && r == -ENOENT)
|
||||
return 0;
|
||||
|
||||
return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
|
||||
}
|
||||
|
||||
f = rf;
|
||||
fn = pp;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
int k;
|
||||
|
||||
k = read_stripped_line(f, LONG_LINE_MAX, &line);
|
||||
if (k < 0)
|
||||
return log_error_errno(k, "Failed to read '%s': %m", fn);
|
||||
if (k == 0)
|
||||
break;
|
||||
|
||||
v++;
|
||||
|
||||
if (IN_SET(line[0], 0, '#'))
|
||||
continue;
|
||||
|
||||
k = parse_line(c, fn, v, line);
|
||||
if (k < 0 && r == 0)
|
||||
r = k;
|
||||
}
|
||||
|
||||
if (ferror(f)) {
|
||||
log_error_errno(errno, "Failed to read from file %s: %m", fn);
|
||||
if (r == 0)
|
||||
r = -EIO;
|
||||
}
|
||||
|
||||
return r;
|
||||
return conf_file_read(
|
||||
arg_root,
|
||||
(const char**) CONF_PATHS_STRV("sysusers.d"),
|
||||
ASSERT_PTR(fn),
|
||||
parse_line,
|
||||
ASSERT_PTR(c),
|
||||
ignore_enoent,
|
||||
/* invalid_config= */ NULL);
|
||||
}
|
||||
|
||||
static int cat_config(void) {
|
||||
@ -2140,10 +2099,12 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_REPLACE:
|
||||
if (!path_is_absolute(optarg) ||
|
||||
!endswith(optarg, ".conf"))
|
||||
if (!path_is_absolute(optarg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"The argument to --replace= must an absolute path to a config file");
|
||||
"The argument to --replace= must be an absolute path.");
|
||||
if (!endswith(optarg, ".conf"))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"The argument to --replace= must have the extension '.conf'.");
|
||||
|
||||
arg_replace = optarg;
|
||||
break;
|
||||
@ -2191,7 +2152,7 @@ static int parse_arguments(Context *c, char **args) {
|
||||
STRV_FOREACH(arg, args) {
|
||||
if (arg_inline)
|
||||
/* Use (argument):n, where n==1 for the first positional arg */
|
||||
r = parse_line(c, "(argument)", pos, *arg);
|
||||
r = parse_line("(argument)", pos, *arg, /* invalid_config= */ NULL, c);
|
||||
else
|
||||
r = read_config_file(c, *arg, /* ignore_enoent= */ false);
|
||||
if (r < 0)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -14,6 +14,14 @@ mkdir /tmp/{C,d,D,e}
|
||||
mkdir /tmp/d/2
|
||||
chmod 777 /tmp/d/2
|
||||
|
||||
systemd-tmpfiles --dry-run --create - <<EOF
|
||||
d /tmp/d/1 0755 daemon daemon - -
|
||||
d /tmp/d/2 0755 daemon daemon - -
|
||||
EOF
|
||||
|
||||
test ! -d /tmp/d/1
|
||||
test -d /tmp/d/2
|
||||
|
||||
systemd-tmpfiles --create - <<EOF
|
||||
d /tmp/d/1 0755 daemon daemon - -
|
||||
d /tmp/d/2 0755 daemon daemon - -
|
||||
@ -104,6 +112,14 @@ chmod 755 /tmp/C/{1,2,3}-origin/f1
|
||||
mkdir /tmp/C/{2,3}
|
||||
touch /tmp/C/3/f1
|
||||
|
||||
systemd-tmpfiles --dry-run --create - <<EOF
|
||||
C /tmp/C/1 0755 daemon daemon - /tmp/C/1-origin
|
||||
C /tmp/C/2 0755 daemon daemon - /tmp/C/2-origin
|
||||
EOF
|
||||
|
||||
test ! -d /tmp/C/1
|
||||
test -d /tmp/C/2
|
||||
|
||||
systemd-tmpfiles --create - <<EOF
|
||||
C /tmp/C/1 0755 daemon daemon - /tmp/C/1-origin
|
||||
C /tmp/C/2 0755 daemon daemon - /tmp/C/2-origin
|
||||
|
@ -12,6 +12,14 @@ touch /tmp/file-owned-by-root
|
||||
#
|
||||
# 'f'
|
||||
#
|
||||
systemd-tmpfiles --dry-run --create - <<EOF
|
||||
f /tmp/f/1 0644 - - - -
|
||||
f /tmp/f/2 0644 - - - This string should be written
|
||||
EOF
|
||||
|
||||
test ! -e /tmp/f/1
|
||||
test ! -e /tmp/f/2
|
||||
|
||||
systemd-tmpfiles --create - <<EOF
|
||||
f /tmp/f/1 0644 - - - -
|
||||
f /tmp/f/2 0644 - - - This string should be written
|
||||
@ -189,6 +197,11 @@ touch /tmp/w/overwritten
|
||||
touch /tmp/w/appended
|
||||
|
||||
### nop if the target does not exist.
|
||||
systemd-tmpfiles --dry-run --create - <<EOF
|
||||
w /tmp/w/unexistent 0644 - - - new content
|
||||
EOF
|
||||
test ! -e /tmp/w/unexistent
|
||||
|
||||
systemd-tmpfiles --create - <<EOF
|
||||
w /tmp/w/unexistent 0644 - - - new content
|
||||
EOF
|
||||
@ -200,6 +213,12 @@ w /tmp/w/unexistent 0644 - - - -
|
||||
EOF
|
||||
|
||||
### write into an empty file.
|
||||
systemd-tmpfiles --dry-run --create - <<EOF
|
||||
w /tmp/w/overwritten 0644 - - - old content
|
||||
EOF
|
||||
test -f /tmp/w/overwritten
|
||||
test -z "$(< /tmp/w/overwritten)"
|
||||
|
||||
systemd-tmpfiles --create - <<EOF
|
||||
w /tmp/w/overwritten 0644 - - - old content
|
||||
EOF
|
||||
@ -207,6 +226,12 @@ test -f /tmp/w/overwritten
|
||||
test "$(< /tmp/w/overwritten)" = "old content"
|
||||
|
||||
### old content is overwritten
|
||||
systemd-tmpfiles --dry-run --create - <<EOF
|
||||
w /tmp/w/overwritten 0644 - - - new content
|
||||
EOF
|
||||
test -f /tmp/w/overwritten
|
||||
test "$(< /tmp/w/overwritten)" = "old content"
|
||||
|
||||
systemd-tmpfiles --create - <<EOF
|
||||
w /tmp/w/overwritten 0644 - - - new content
|
||||
EOF
|
||||
@ -223,6 +248,10 @@ test -f /tmp/w/appended
|
||||
test "$(< /tmp/w/appended)" = "$(echo -ne '12\n3')"
|
||||
|
||||
### writing into an 'exotic' file should be allowed.
|
||||
systemd-tmpfiles --dry-run --create - <<EOF
|
||||
w /dev/null - - - - new content
|
||||
EOF
|
||||
|
||||
systemd-tmpfiles --create - <<EOF
|
||||
w /dev/null - - - - new content
|
||||
EOF
|
||||
|
@ -9,6 +9,12 @@ rm -fr /tmp/p
|
||||
mkdir /tmp/p
|
||||
touch /tmp/p/f1
|
||||
|
||||
systemd-tmpfiles --dry-run --create - <<EOF
|
||||
p /tmp/p/fifo1 0666 - - - -
|
||||
EOF
|
||||
|
||||
test ! -p /tmp/p/fifo1
|
||||
|
||||
systemd-tmpfiles --create - <<EOF
|
||||
p /tmp/p/fifo1 0666 - - - -
|
||||
EOF
|
||||
|
@ -12,6 +12,15 @@ mkdir /tmp/{z,Z}
|
||||
mkdir /tmp/z/d{1,2}
|
||||
touch /tmp/z/f1 /tmp/z/d1/f11 /tmp/z/d2/f21
|
||||
|
||||
systemd-tmpfiles --dry-run --create - <<EOF
|
||||
z /tmp/z/f1 0755 daemon daemon - -
|
||||
z /tmp/z/d1 0755 daemon daemon - -
|
||||
EOF
|
||||
|
||||
test "$(stat -c %U /tmp/z/f1)" = "$USER"
|
||||
test "$(stat -c %U /tmp/z/d1)" = "$USER"
|
||||
test "$(stat -c %U /tmp/z/d1/f11)" = "$USER"
|
||||
|
||||
systemd-tmpfiles --create - <<EOF
|
||||
z /tmp/z/f1 0755 daemon daemon - -
|
||||
z /tmp/z/d1 0755 daemon daemon - -
|
||||
|
@ -6,7 +6,14 @@ set -eux
|
||||
set -o pipefail
|
||||
|
||||
test_snippet() {
|
||||
systemd-tmpfiles "$@" - <<EOF
|
||||
# First call with --dry-run to test the code paths
|
||||
systemd-tmpfiles --dry-run "$@" - <<EOF
|
||||
d /var/tmp/foobar-test-06
|
||||
d /var/tmp/foobar-test-06/important
|
||||
R /var/tmp/foobar-test-06
|
||||
EOF
|
||||
|
||||
systemd-tmpfiles "$@" - <<EOF
|
||||
d /var/tmp/foobar-test-06
|
||||
d /var/tmp/foobar-test-06/important
|
||||
R /var/tmp/foobar-test-06
|
||||
|
@ -12,6 +12,19 @@ mkdir /tmp/x
|
||||
mkdir -p /tmp/x/{1,2}
|
||||
touch /tmp/x/1/{x1,x2} /tmp/x/2/{y1,y2} /tmp/x/{z1,z2}
|
||||
|
||||
systemd-tmpfiles --clean --dry-run - <<EOF
|
||||
d /tmp/x - - - 0
|
||||
x /tmp/x/1
|
||||
EOF
|
||||
|
||||
find /tmp/x | sort
|
||||
test -f /tmp/x/1/x1
|
||||
test -f /tmp/x/1/x2
|
||||
test -f /tmp/x/2/y1
|
||||
test -f /tmp/x/2/y2
|
||||
test -f /tmp/x/z1
|
||||
test -f /tmp/x/z2
|
||||
|
||||
systemd-tmpfiles --clean - <<EOF
|
||||
d /tmp/x - - - 0
|
||||
x /tmp/x/1
|
||||
@ -34,6 +47,19 @@ test ! -f /tmp/x/z2
|
||||
mkdir -p /tmp/x/{1,2}
|
||||
touch /tmp/x/1/{x1,x2} /tmp/x/2/{y1,y2} /tmp/x/{z1,z2}
|
||||
|
||||
systemd-tmpfiles --dry-run --clean - <<EOF
|
||||
d /tmp/x - - - 0
|
||||
X /tmp/x/1
|
||||
EOF
|
||||
|
||||
find /tmp/x | sort
|
||||
test -f /tmp/x/1/x1
|
||||
test -f /tmp/x/1/x2
|
||||
test -f /tmp/x/2/y1
|
||||
test -f /tmp/x/2/y2
|
||||
test -f /tmp/x/z1
|
||||
test -f /tmp/x/z2
|
||||
|
||||
systemd-tmpfiles --clean - <<EOF
|
||||
d /tmp/x - - - 0
|
||||
X /tmp/x/1
|
||||
@ -56,6 +82,20 @@ test ! -f /tmp/x/z2
|
||||
mkdir -p /tmp/x/{1,2}
|
||||
touch /tmp/x/1/{x1,x2} /tmp/x/2/{y1,y2} /tmp/x/{z1,z2}
|
||||
|
||||
systemd-tmpfiles --dry-run --clean - <<EOF
|
||||
d /tmp/x - - - 0
|
||||
x /tmp/x/[1345]
|
||||
x /tmp/x/z*
|
||||
EOF
|
||||
|
||||
find /tmp/x | sort
|
||||
test -f /tmp/x/1/x1
|
||||
test -f /tmp/x/1/x2
|
||||
test -f /tmp/x/2/y1
|
||||
test -f /tmp/x/2/y2
|
||||
test -f /tmp/x/z1
|
||||
test -f /tmp/x/z2
|
||||
|
||||
systemd-tmpfiles --clean - <<EOF
|
||||
d /tmp/x - - - 0
|
||||
x /tmp/x/[1345]
|
||||
@ -79,6 +119,20 @@ test -f /tmp/x/z2
|
||||
mkdir -p /tmp/x/{1,2}
|
||||
touch /tmp/x/1/{x1,x2} /tmp/x/2/{y1,y2} /tmp/x/{z1,z2}
|
||||
|
||||
systemd-tmpfiles --dry-run --clean - <<EOF
|
||||
d /tmp/x - - - 0
|
||||
X /tmp/x/[1345]
|
||||
X /tmp/x/?[12]
|
||||
EOF
|
||||
|
||||
find /tmp/x | sort
|
||||
test -f /tmp/x/1/x1
|
||||
test -f /tmp/x/1/x2
|
||||
test -f /tmp/x/2/y1
|
||||
test -f /tmp/x/2/y2
|
||||
test -f /tmp/x/z1
|
||||
test -f /tmp/x/z2
|
||||
|
||||
systemd-tmpfiles --clean - <<EOF
|
||||
d /tmp/x - - - 0
|
||||
X /tmp/x/[1345]
|
||||
@ -102,6 +156,19 @@ test -f /tmp/x/z2
|
||||
mkdir -p /tmp/x/{1,2}/a
|
||||
touch /tmp/x/1/a/{x1,x2} /tmp/x/2/a/{y1,y2}
|
||||
|
||||
systemd-tmpfiles --dry-run --clean - <<EOF
|
||||
# x/X is not supposed to influence r
|
||||
x /tmp/x/1/a
|
||||
X /tmp/x/2/a
|
||||
r /tmp/x/1
|
||||
r /tmp/x/2
|
||||
EOF
|
||||
|
||||
test -f /tmp/x/1/a/x1
|
||||
test -f /tmp/x/1/a/x2
|
||||
test -f /tmp/x/2/a/y1
|
||||
test -f /tmp/x/2/a/y2
|
||||
|
||||
systemd-tmpfiles --clean - <<EOF
|
||||
# x/X is not supposed to influence r
|
||||
x /tmp/x/1/a
|
||||
@ -125,17 +192,58 @@ test -f /tmp/x/2/a/y2
|
||||
mkdir -p /tmp/x/{1,2}/a
|
||||
touch /tmp/x/1/a/{x1,x2} /tmp/x/2/a/{y1,y2}
|
||||
|
||||
systemd-tmpfiles --dry-run --remove - <<EOF
|
||||
# Check that X is honoured below R
|
||||
X /tmp/x/1/a
|
||||
X /tmp/x/2/a
|
||||
R /tmp/x/1
|
||||
EOF
|
||||
|
||||
test -f /tmp/x/1/a/x1
|
||||
test -f /tmp/x/1/a/x2
|
||||
test -f /tmp/x/2/a/y1
|
||||
test -f /tmp/x/2/a/y2
|
||||
|
||||
systemd-tmpfiles --remove - <<EOF
|
||||
# X is not supposed to influence R
|
||||
# Check that X is honoured below R
|
||||
X /tmp/x/1/a
|
||||
X /tmp/x/2/a
|
||||
R /tmp/x/1
|
||||
EOF
|
||||
|
||||
find /tmp/x | sort
|
||||
test ! -d /tmp/x/1
|
||||
test ! -d /tmp/x/1/a
|
||||
test ! -f /tmp/x/1/a/x1
|
||||
test ! -f /tmp/x/1/a/x2
|
||||
test -d /tmp/x/1
|
||||
test -d /tmp/x/1/a
|
||||
test -f /tmp/x/1/a/x1
|
||||
test -f /tmp/x/1/a/x2
|
||||
test -f /tmp/x/2/a/y1
|
||||
test -f /tmp/x/2/a/y2
|
||||
|
||||
#
|
||||
# 'r/R/D' and non-directories
|
||||
#
|
||||
|
||||
touch /tmp/x/{11,22,33}
|
||||
|
||||
systemd-tmpfiles --dry-run --remove - <<EOF
|
||||
# Check that X is honoured below R
|
||||
r /tmp/x/11
|
||||
R /tmp/x/22
|
||||
D /tmp/x/33
|
||||
EOF
|
||||
|
||||
test -f /tmp/x/11
|
||||
test -f /tmp/x/22
|
||||
test -f /tmp/x/33
|
||||
|
||||
systemd-tmpfiles --remove - <<EOF
|
||||
# Check that X is honoured below R
|
||||
r /tmp/x/11
|
||||
R /tmp/x/22
|
||||
D /tmp/x/33
|
||||
EOF
|
||||
|
||||
find /tmp/x | sort
|
||||
test ! -f /tmp/x/11
|
||||
test ! -f /tmp/x/22
|
||||
test -f /tmp/x/33
|
||||
|
@ -52,6 +52,16 @@ sleep 1
|
||||
touch /tmp/ageby/d{3,4}/f{2..4}
|
||||
|
||||
# Check for cleanup of "f1" in each of "/tmp/d{1..4}".
|
||||
systemd-tmpfiles --dry-run --clean - <<-EOF
|
||||
d /tmp/ageby/d1 - - - a:1m -
|
||||
e /tmp/ageby/d2 - - - m:3m -
|
||||
D /tmp/ageby/d3 - - - c:2s -
|
||||
EOF
|
||||
|
||||
for d in d{1..3}; do
|
||||
test -f "/tmp/ageby/${d}/f1"
|
||||
done
|
||||
|
||||
systemd-tmpfiles --clean - <<-EOF
|
||||
d /tmp/ageby/d1 - - - a:1m -
|
||||
e /tmp/ageby/d2 - - - m:3m -
|
||||
|
@ -12,6 +12,12 @@ mkdir /tmp/L
|
||||
home='/somewhere'
|
||||
dst='/tmp/L/1'
|
||||
src="$home"
|
||||
HOME="$home" \
|
||||
systemd-tmpfiles --dry-run --create - <<EOF
|
||||
L $dst - - - - %h
|
||||
EOF
|
||||
test ! -h "$dst"
|
||||
|
||||
HOME="$home" \
|
||||
systemd-tmpfiles --create - <<EOF
|
||||
L $dst - - - - %h
|
||||
@ -25,6 +31,12 @@ home='/%U'
|
||||
src="/usr/share/factory$home"
|
||||
mkdir -p "$root$src"
|
||||
dst="$root$home"
|
||||
HOME="$home" \
|
||||
systemd-tmpfiles --create --dry-run --root="$root" - <<EOF
|
||||
L %h - - - -
|
||||
EOF
|
||||
test ! -h "$dst"
|
||||
|
||||
HOME="$home" \
|
||||
systemd-tmpfiles --create --root="$root" - <<EOF
|
||||
L %h - - - -
|
||||
|
@ -12,6 +12,11 @@ rm -f /tmp/acl_exec
|
||||
touch /tmp/acl_exec
|
||||
|
||||
# No ACL set yet
|
||||
systemd-tmpfiles --dry-run --create - <<EOF
|
||||
a /tmp/acl_exec - - - - u:root:rwX
|
||||
EOF
|
||||
assert_not_in 'user:root:rw-' "$(getfacl -Ec /tmp/acl_exec)"
|
||||
|
||||
systemd-tmpfiles --create - <<EOF
|
||||
a /tmp/acl_exec - - - - u:root:rwX
|
||||
EOF
|
||||
|
@ -8,26 +8,27 @@ set -o pipefail
|
||||
|
||||
export SYSTEMD_LOG_LEVEL=debug
|
||||
|
||||
systemd-tmpfiles --create - <<EOF
|
||||
c='
|
||||
d /tmp/somedir
|
||||
f /tmp/somedir/somefile - - - - baz
|
||||
EOF
|
||||
'
|
||||
|
||||
systemd-tmpfiles --create - <<<"$c"
|
||||
test -f /tmp/somedir/somefile
|
||||
grep -q baz /tmp/somedir/somefile
|
||||
|
||||
systemd-tmpfiles --purge - <<EOF
|
||||
d /tmp/somedir
|
||||
f /tmp/somedir/somefile - - - - baz
|
||||
EOF
|
||||
systemd-tmpfiles --purge --dry-run - <<<"$c"
|
||||
test -f /tmp/somedir/somefile
|
||||
grep -q baz /tmp/somedir/somefile
|
||||
|
||||
systemd-tmpfiles --purge - <<<"$c"
|
||||
test ! -f /tmp/somedir/somefile
|
||||
test ! -d /tmp/somedir/
|
||||
|
||||
systemd-tmpfiles --create --purge - <<EOF
|
||||
d /tmp/somedir
|
||||
f /tmp/somedir/somefile - - - - baz
|
||||
EOF
|
||||
systemd-tmpfiles --create --purge --dry-run - <<<"$c"
|
||||
test ! -f /tmp/somedir/somefile
|
||||
test ! -d /tmp/somedir/
|
||||
|
||||
systemd-tmpfiles --create --purge - <<<"$c"
|
||||
test -f /tmp/somedir/somefile
|
||||
grep -q baz /tmp/somedir/somefile
|
||||
|
29
test/units/testsuite-22.19.sh
Executable file
29
test/units/testsuite-22.19.sh
Executable file
@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# Tests for character and block device creation
|
||||
#
|
||||
set -eux
|
||||
set -o pipefail
|
||||
|
||||
rm -rf /tmp/dev
|
||||
mkdir /tmp/dev
|
||||
|
||||
# We are running tests in /tmp, which would normally be mounted nodev,
|
||||
# so we only try with --dry-run.
|
||||
|
||||
systemd-tmpfiles --dry-run --create - <<EOF
|
||||
c /tmp/dev/char - - - - 11:12
|
||||
b /tmp/dev/block - - - - 11:14
|
||||
EOF
|
||||
|
||||
test ! -e /tmp/dev/char
|
||||
test ! -e /tmp/dev/block
|
||||
|
||||
systemd-tmpfiles --dry-run --create - <<EOF
|
||||
c+ /tmp/dev/char - - - - 11:12
|
||||
b+ /tmp/dev/block - - - - 11:14
|
||||
EOF
|
||||
|
||||
test ! -e /tmp/dev/char
|
||||
test ! -e /tmp/dev/block
|
@ -169,9 +169,9 @@ systemd-nspawn.xml /refsect1[title="Options"]/refsect2[title="Execution Options"
|
||||
systemd-nspawn.xml /refsect1[title="Options"]/refsect2[title="System Identity Options"]/variablelist/varlistentry[term="--uuid="]
|
||||
systemd-nspawn.xml /refsect1[title="Options"]/refsect2[title="Networking Options"]/variablelist/varlistentry[term="--private-network"]
|
||||
systemd-nspawn.xml /refsect1[title="Options"]/refsect2[title="Image Options"]/variablelist/varlistentry[term="--read-only"]
|
||||
systemd-tmpfiles.xml /refsect1[title="Options"]/variablelist/varlistentry[term="--create"]
|
||||
systemd-tmpfiles.xml /refsect1[title="Options"]/variablelist/varlistentry[term="--clean"]
|
||||
systemd-tmpfiles.xml /refsect1[title="Options"]/variablelist/varlistentry[term="--remove"]
|
||||
systemd-tmpfiles.xml /refsect1[title="Commands and options"]/variablelist/varlistentry[term="--create"]
|
||||
systemd-tmpfiles.xml /refsect1[title="Commands and options"]/variablelist/varlistentry[term="--clean"]
|
||||
systemd-tmpfiles.xml /refsect1[title="Commands and options"]/variablelist/varlistentry[term="--remove"]
|
||||
systemd-tmpfiles.xml /refsect1[title="Options"]/variablelist/varlistentry[term="--prefix=path"]
|
||||
systemd.automount.xml /refsect1[title="Options"]/variablelist/varlistentry[term="Where="]
|
||||
systemd.automount.xml /refsect1[title="Options"]/variablelist/varlistentry[term="DirectoryMode="]
|
||||
|
Loading…
Reference in New Issue
Block a user