mirror of
https://github.com/systemd/systemd
synced 2026-03-19 11:34:46 +01:00
Compare commits
32 Commits
6222acc2b5
...
eb70d9450c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb70d9450c | ||
|
|
86e24d608a | ||
|
|
6abd991c71 | ||
|
|
5bf7d8f04d | ||
|
|
04d54d5011 | ||
|
|
1001167ca5 | ||
|
|
280e4b368e | ||
|
|
4ef65db34b | ||
|
|
c1e4c62235 | ||
|
|
b80ef40caf | ||
|
|
ac19bdd04b | ||
|
|
0fb789af20 | ||
|
|
da90c261af | ||
|
|
c3b8bacd7b | ||
|
|
cd503dbb6b | ||
|
|
d32f7a8e9b | ||
|
|
1622ef77ee | ||
|
|
fff25ab22e | ||
|
|
87501ac0eb | ||
|
|
b25a930f0e | ||
|
|
2d32453bc8 | ||
|
|
6a818c3cb4 | ||
|
|
37350b81b5 | ||
|
|
2686114332 | ||
|
|
65ddc2c5ff | ||
|
|
f565b8676f | ||
|
|
98f7a4c8bb | ||
|
|
6d216bdd07 | ||
|
|
a79726113a | ||
|
|
aa45911b79 | ||
|
|
9c6535367d | ||
|
|
f69c2926f8 |
4
TODO
4
TODO
@ -885,6 +885,10 @@ Features:
|
|||||||
|
|
||||||
* fstab-generator: default to tmpfs-as-root if only usr= is specified on the kernel cmdline
|
* fstab-generator: default to tmpfs-as-root if only usr= is specified on the kernel cmdline
|
||||||
|
|
||||||
|
* initrd-parse-etc.service: can we skip daemon-reload if /sysroot/etc/fstab is missing?
|
||||||
|
Note that we start initrd-fs.target and initrd-cleanup.target there, so a straightforward
|
||||||
|
ConditionPathExists= is not enough.
|
||||||
|
|
||||||
* docs: bring http://www.freedesktop.org/wiki/Software/systemd/MyServiceCantGetRealtime up to date
|
* docs: bring http://www.freedesktop.org/wiki/Software/systemd/MyServiceCantGetRealtime up to date
|
||||||
|
|
||||||
* add a job mode that will fail if a transaction would mean stopping
|
* add a job mode that will fail if a transaction would mean stopping
|
||||||
|
|||||||
3
docs/.gitignore
vendored
3
docs/.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
_site
|
/_site/
|
||||||
|
/.jekyll-cache/
|
||||||
|
|||||||
@ -5,8 +5,8 @@ XDG_DATA_DIRS="${XDG_DATA_DIRS:-/usr/local/share/:/usr/share}"
|
|||||||
|
|
||||||
# add a directory if it exists
|
# add a directory if it exists
|
||||||
if [[ -d /opt/foo/share ]]; then
|
if [[ -d /opt/foo/share ]]; then
|
||||||
XDG_DATA_DIRS=/opt/foo/share:${XDG_DATA_DIRS}
|
XDG_DATA_DIRS="/opt/foo/share:${XDG_DATA_DIRS}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# write our output
|
# write our output
|
||||||
echo XDG_DATA_DIRS=$XDG_DATA_DIRS
|
echo "XDG_DATA_DIRS=${XDG_DATA_DIRS}"
|
||||||
|
|||||||
@ -210,10 +210,19 @@
|
|||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--no-output</option></term>
|
<term><option>--no-output</option></term>
|
||||||
|
|
||||||
<listitem><para>Do not print passwords to standard output.
|
<listitem><para>Do not print passwords to standard output. This is useful if you want to store a
|
||||||
This is useful if you want to store a password in kernel
|
password in kernel keyring with <option>--keyname=</option> but do not want it to show up on screen
|
||||||
keyring with <option>--keyname</option> but do not want it
|
or in logs.</para></listitem>
|
||||||
to show up on screen or in logs.</para></listitem>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-n</option></term>
|
||||||
|
|
||||||
|
<listitem><para>By default, when writing the acquired password to standard output it is suffixed by a
|
||||||
|
newline character. This may be turned off with the <option>-n</option> switch, similar to the switch
|
||||||
|
of the same name of the <citerefentry
|
||||||
|
project='man-pages'><refentrytitle>echo</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||||
|
command.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<xi:include href="standard-options.xml" xpointer="help" />
|
<xi:include href="standard-options.xml" xpointer="help" />
|
||||||
|
|||||||
@ -1707,7 +1707,6 @@ install_libsystemd_static = static_library(
|
|||||||
libcap,
|
libcap,
|
||||||
libblkid,
|
libblkid,
|
||||||
libmount,
|
libmount,
|
||||||
libselinux,
|
|
||||||
libgcrypt],
|
libgcrypt],
|
||||||
c_args : libsystemd_c_args + (static_libsystemd_pic ? [] : ['-fno-PIC']))
|
c_args : libsystemd_c_args + (static_libsystemd_pic ? [] : ['-fno-PIC']))
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,7 @@ static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC;
|
|||||||
static bool arg_multiple = false;
|
static bool arg_multiple = false;
|
||||||
static bool arg_no_output = false;
|
static bool arg_no_output = false;
|
||||||
static AskPasswordFlags arg_flags = ASK_PASSWORD_PUSH_CACHE;
|
static AskPasswordFlags arg_flags = ASK_PASSWORD_PUSH_CACHE;
|
||||||
|
static bool arg_newline = true;
|
||||||
|
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_message, freep);
|
STATIC_DESTRUCTOR_REGISTER(arg_message, freep);
|
||||||
|
|
||||||
@ -54,6 +55,8 @@ static int help(void) {
|
|||||||
" --accept-cached Accept cached passwords\n"
|
" --accept-cached Accept cached passwords\n"
|
||||||
" --multiple List multiple passwords if available\n"
|
" --multiple List multiple passwords if available\n"
|
||||||
" --no-output Do not print password to standard output\n"
|
" --no-output Do not print password to standard output\n"
|
||||||
|
" -n Do not suffix password written to standard output with\n"
|
||||||
|
" newline\n"
|
||||||
"\nSee the %2$s for details.\n",
|
"\nSee the %2$s for details.\n",
|
||||||
program_invocation_short_name,
|
program_invocation_short_name,
|
||||||
link,
|
link,
|
||||||
@ -104,7 +107,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
|
|
||||||
/* Note the asymmetry: the long option --echo= allows an optional argument, the short option does
|
/* Note the asymmetry: the long option --echo= allows an optional argument, the short option does
|
||||||
* not. */
|
* not. */
|
||||||
while ((c = getopt_long(argc, argv, "+he", options, NULL)) >= 0)
|
while ((c = getopt_long(argc, argv, "+hen", options, NULL)) >= 0)
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
|
||||||
@ -177,6 +180,10 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
arg_credential_name = optarg;
|
arg_credential_name = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'n':
|
||||||
|
arg_newline = false;
|
||||||
|
break;
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@ -237,8 +244,14 @@ static int run(int argc, char *argv[]) {
|
|||||||
return log_error_errno(r, "Failed to query password: %m");
|
return log_error_errno(r, "Failed to query password: %m");
|
||||||
|
|
||||||
STRV_FOREACH(p, l) {
|
STRV_FOREACH(p, l) {
|
||||||
if (!arg_no_output)
|
if (!arg_no_output) {
|
||||||
|
if (arg_newline)
|
||||||
puts(*p);
|
puts(*p);
|
||||||
|
else
|
||||||
|
fputs(*p, stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
if (!arg_multiple)
|
if (!arg_multiple)
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
|
|
||||||
int dirent_ensure_type(DIR *d, struct dirent *de) {
|
static int dirent_ensure_type(DIR *d, struct dirent *de) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
assert(d);
|
assert(d);
|
||||||
@ -59,11 +59,23 @@ bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
|
|||||||
return endswith(de->d_name, suffix);
|
return endswith(de->d_name, suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct dirent *readdir_ensure_type(DIR *d) {
|
||||||
|
struct dirent *de;
|
||||||
|
|
||||||
|
assert(d);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
de = readdir(d);
|
||||||
|
if (de)
|
||||||
|
(void) dirent_ensure_type(d, de);
|
||||||
|
return de;
|
||||||
|
}
|
||||||
|
|
||||||
struct dirent *readdir_no_dot(DIR *dirp) {
|
struct dirent *readdir_no_dot(DIR *dirp) {
|
||||||
struct dirent *d;
|
struct dirent *d;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
d = readdir(dirp);
|
d = readdir_ensure_type(dirp);
|
||||||
if (d && dot_or_dot_dot(d->d_name))
|
if (d && dot_or_dot_dot(d->d_name))
|
||||||
continue;
|
continue;
|
||||||
return d;
|
return d;
|
||||||
|
|||||||
@ -8,15 +8,14 @@
|
|||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
|
|
||||||
int dirent_ensure_type(DIR *d, struct dirent *de);
|
|
||||||
|
|
||||||
bool dirent_is_file(const struct dirent *de) _pure_;
|
bool dirent_is_file(const struct dirent *de) _pure_;
|
||||||
bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_;
|
bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_;
|
||||||
|
|
||||||
|
struct dirent *readdir_ensure_type(DIR *d);
|
||||||
struct dirent *readdir_no_dot(DIR *dirp);
|
struct dirent *readdir_no_dot(DIR *dirp);
|
||||||
|
|
||||||
#define FOREACH_DIRENT(de, d, on_error) \
|
#define FOREACH_DIRENT(de, d, on_error) \
|
||||||
for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \
|
for (de = readdir_ensure_type(d);; de = readdir_ensure_type(d)) \
|
||||||
if (!de) { \
|
if (!de) { \
|
||||||
if (errno > 0) { \
|
if (errno > 0) { \
|
||||||
on_error; \
|
on_error; \
|
||||||
@ -27,7 +26,7 @@ struct dirent* readdir_no_dot(DIR *dirp);
|
|||||||
else
|
else
|
||||||
|
|
||||||
#define FOREACH_DIRENT_ALL(de, d, on_error) \
|
#define FOREACH_DIRENT_ALL(de, d, on_error) \
|
||||||
for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \
|
for (de = readdir_ensure_type(d);; de = readdir_ensure_type(d)) \
|
||||||
if (!de) { \
|
if (!de) { \
|
||||||
if (errno > 0) { \
|
if (errno > 0) { \
|
||||||
on_error; \
|
on_error; \
|
||||||
|
|||||||
@ -1,40 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
||||||
|
|
||||||
#include "dlfcn-util.h"
|
|
||||||
|
|
||||||
int dlsym_many_and_warn(void *dl, int level, ...) {
|
|
||||||
va_list ap;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
/* Tries to resolve a bunch of function symbols, and logs errors about the ones it cannot
|
|
||||||
* resolve. Note that this function possibly modifies the supplied function pointers if the whole
|
|
||||||
* operation fails */
|
|
||||||
|
|
||||||
va_start(ap, level);
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
void (**fn)(void);
|
|
||||||
void (*tfn)(void);
|
|
||||||
const char *symbol;
|
|
||||||
|
|
||||||
fn = va_arg(ap, typeof(fn));
|
|
||||||
if (!fn)
|
|
||||||
break;
|
|
||||||
|
|
||||||
symbol = va_arg(ap, typeof(symbol));
|
|
||||||
|
|
||||||
tfn = (typeof(tfn)) dlsym(dl, symbol);
|
|
||||||
if (!tfn) {
|
|
||||||
r = log_full_errno(level,
|
|
||||||
SYNTHETIC_ERRNO(ELIBBAD),
|
|
||||||
"Can't find symbol %s: %s", symbol, dlerror());
|
|
||||||
va_end(ap);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
*fn = tfn;
|
|
||||||
}
|
|
||||||
|
|
||||||
va_end(ap);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <dlfcn.h>
|
|
||||||
|
|
||||||
#include "macro.h"
|
|
||||||
|
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(void*, dlclose, NULL);
|
|
||||||
|
|
||||||
int dlsym_many_and_warn(void *dl, int level, ...);
|
|
||||||
|
|
||||||
/* Macro useful for putting together variable/symbol name pairs when calling dlsym_many_and_warn(). Assumes
|
|
||||||
* that each library symbol to resolve will be placed in a variable with the "sym_" prefix, i.e. a symbol
|
|
||||||
* "foobar" is loaded into a variable "sym_foobar". */
|
|
||||||
#define DLSYM_ARG(arg) \
|
|
||||||
&sym_##arg, STRINGIFY(arg)
|
|
||||||
@ -2,19 +2,20 @@
|
|||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <linux/btrfs.h>
|
||||||
|
#include <linux/magic.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "copy.h"
|
|
||||||
#include "dirent-util.h"
|
#include "dirent-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "fs-util.h"
|
#include "fs-util.h"
|
||||||
#include "io-util.h"
|
#include "io-util.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
#include "memfd-util.h"
|
|
||||||
#include "missing_fcntl.h"
|
#include "missing_fcntl.h"
|
||||||
#include "missing_syscall.h"
|
#include "missing_syscall.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
@ -520,343 +521,6 @@ int move_fd(int from, int to, int cloexec) {
|
|||||||
return to;
|
return to;
|
||||||
}
|
}
|
||||||
|
|
||||||
int acquire_data_fd(const void *data, size_t size, unsigned flags) {
|
|
||||||
|
|
||||||
_cleanup_close_pair_ int pipefds[2] = { -1, -1 };
|
|
||||||
char pattern[] = "/dev/shm/data-fd-XXXXXX";
|
|
||||||
_cleanup_close_ int fd = -1;
|
|
||||||
int isz = 0, r;
|
|
||||||
ssize_t n;
|
|
||||||
off_t f;
|
|
||||||
|
|
||||||
assert(data || size == 0);
|
|
||||||
|
|
||||||
/* Acquire a read-only file descriptor that when read from returns the specified data. This is much more
|
|
||||||
* complex than I wish it was. But here's why:
|
|
||||||
*
|
|
||||||
* a) First we try to use memfds. They are the best option, as we can seal them nicely to make them
|
|
||||||
* read-only. Unfortunately they require kernel 3.17, and – at the time of writing – we still support 3.14.
|
|
||||||
*
|
|
||||||
* b) Then, we try classic pipes. They are the second best options, as we can close the writing side, retaining
|
|
||||||
* a nicely read-only fd in the reading side. However, they are by default quite small, and unprivileged
|
|
||||||
* clients can only bump their size to a system-wide limit, which might be quite low.
|
|
||||||
*
|
|
||||||
* c) Then, we try an O_TMPFILE file in /dev/shm (that dir is the only suitable one known to exist from
|
|
||||||
* earliest boot on). To make it read-only we open the fd a second time with O_RDONLY via
|
|
||||||
* /proc/self/<fd>. Unfortunately O_TMPFILE is not available on older kernels on tmpfs.
|
|
||||||
*
|
|
||||||
* d) Finally, we try creating a regular file in /dev/shm, which we then delete.
|
|
||||||
*
|
|
||||||
* It sucks a bit that depending on the situation we return very different objects here, but that's Linux I
|
|
||||||
* figure. */
|
|
||||||
|
|
||||||
if (size == 0 && ((flags & ACQUIRE_NO_DEV_NULL) == 0)) {
|
|
||||||
/* As a special case, return /dev/null if we have been called for an empty data block */
|
|
||||||
r = open("/dev/null", O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
|
||||||
if (r < 0)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & ACQUIRE_NO_MEMFD) == 0) {
|
|
||||||
fd = memfd_new("data-fd");
|
|
||||||
if (fd < 0)
|
|
||||||
goto try_pipe;
|
|
||||||
|
|
||||||
n = write(fd, data, size);
|
|
||||||
if (n < 0)
|
|
||||||
return -errno;
|
|
||||||
if ((size_t) n != size)
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
f = lseek(fd, 0, SEEK_SET);
|
|
||||||
if (f != 0)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
r = memfd_set_sealed(fd);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
return TAKE_FD(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
try_pipe:
|
|
||||||
if ((flags & ACQUIRE_NO_PIPE) == 0) {
|
|
||||||
if (pipe2(pipefds, O_CLOEXEC|O_NONBLOCK) < 0)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
|
|
||||||
if (isz < 0)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
if ((size_t) isz < size) {
|
|
||||||
isz = (int) size;
|
|
||||||
if (isz < 0 || (size_t) isz != size)
|
|
||||||
return -E2BIG;
|
|
||||||
|
|
||||||
/* Try to bump the pipe size */
|
|
||||||
(void) fcntl(pipefds[1], F_SETPIPE_SZ, isz);
|
|
||||||
|
|
||||||
/* See if that worked */
|
|
||||||
isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
|
|
||||||
if (isz < 0)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
if ((size_t) isz < size)
|
|
||||||
goto try_dev_shm;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = write(pipefds[1], data, size);
|
|
||||||
if (n < 0)
|
|
||||||
return -errno;
|
|
||||||
if ((size_t) n != size)
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
(void) fd_nonblock(pipefds[0], false);
|
|
||||||
|
|
||||||
return TAKE_FD(pipefds[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
try_dev_shm:
|
|
||||||
if ((flags & ACQUIRE_NO_TMPFILE) == 0) {
|
|
||||||
fd = open("/dev/shm", O_RDWR|O_TMPFILE|O_CLOEXEC, 0500);
|
|
||||||
if (fd < 0)
|
|
||||||
goto try_dev_shm_without_o_tmpfile;
|
|
||||||
|
|
||||||
n = write(fd, data, size);
|
|
||||||
if (n < 0)
|
|
||||||
return -errno;
|
|
||||||
if ((size_t) n != size)
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
/* Let's reopen the thing, in order to get an O_RDONLY fd for the original O_RDWR one */
|
|
||||||
return fd_reopen(fd, O_RDONLY|O_CLOEXEC);
|
|
||||||
}
|
|
||||||
|
|
||||||
try_dev_shm_without_o_tmpfile:
|
|
||||||
if ((flags & ACQUIRE_NO_REGULAR) == 0) {
|
|
||||||
fd = mkostemp_safe(pattern);
|
|
||||||
if (fd < 0)
|
|
||||||
return fd;
|
|
||||||
|
|
||||||
n = write(fd, data, size);
|
|
||||||
if (n < 0) {
|
|
||||||
r = -errno;
|
|
||||||
goto unlink_and_return;
|
|
||||||
}
|
|
||||||
if ((size_t) n != size) {
|
|
||||||
r = -EIO;
|
|
||||||
goto unlink_and_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Let's reopen the thing, in order to get an O_RDONLY fd for the original O_RDWR one */
|
|
||||||
r = open(pattern, O_RDONLY|O_CLOEXEC);
|
|
||||||
if (r < 0)
|
|
||||||
r = -errno;
|
|
||||||
|
|
||||||
unlink_and_return:
|
|
||||||
(void) unlink(pattern);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* When the data is smaller or equal to 64K, try to place the copy in a memfd/pipe */
|
|
||||||
#define DATA_FD_MEMORY_LIMIT (64U*1024U)
|
|
||||||
|
|
||||||
/* If memfd/pipe didn't work out, then let's use a file in /tmp up to a size of 1M. If it's large than that use /var/tmp instead. */
|
|
||||||
#define DATA_FD_TMP_LIMIT (1024U*1024U)
|
|
||||||
|
|
||||||
int fd_duplicate_data_fd(int fd) {
|
|
||||||
|
|
||||||
_cleanup_close_ int copy_fd = -1, tmp_fd = -1;
|
|
||||||
_cleanup_free_ void *remains = NULL;
|
|
||||||
size_t remains_size = 0;
|
|
||||||
const char *td;
|
|
||||||
struct stat st;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
/* Creates a 'data' fd from the specified source fd, containing all the same data in a read-only fashion, but
|
|
||||||
* independent of it (i.e. the source fd can be closed and unmounted after this call succeeded). Tries to be
|
|
||||||
* somewhat smart about where to place the data. In the best case uses a memfd(). If memfd() are not supported
|
|
||||||
* uses a pipe instead. For larger data will use an unlinked file in /tmp, and for even larger data one in
|
|
||||||
* /var/tmp. */
|
|
||||||
|
|
||||||
if (fstat(fd, &st) < 0)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
/* For now, let's only accept regular files, sockets, pipes and char devices */
|
|
||||||
if (S_ISDIR(st.st_mode))
|
|
||||||
return -EISDIR;
|
|
||||||
if (S_ISLNK(st.st_mode))
|
|
||||||
return -ELOOP;
|
|
||||||
if (!S_ISREG(st.st_mode) && !S_ISSOCK(st.st_mode) && !S_ISFIFO(st.st_mode) && !S_ISCHR(st.st_mode))
|
|
||||||
return -EBADFD;
|
|
||||||
|
|
||||||
/* If we have reason to believe the data is bounded in size, then let's use memfds or pipes as backing fd. Note
|
|
||||||
* that we use the reported regular file size only as a hint, given that there are plenty special files in
|
|
||||||
* /proc and /sys which report a zero file size but can be read from. */
|
|
||||||
|
|
||||||
if (!S_ISREG(st.st_mode) || st.st_size < DATA_FD_MEMORY_LIMIT) {
|
|
||||||
|
|
||||||
/* Try a memfd first */
|
|
||||||
copy_fd = memfd_new("data-fd");
|
|
||||||
if (copy_fd >= 0) {
|
|
||||||
off_t f;
|
|
||||||
|
|
||||||
r = copy_bytes(fd, copy_fd, DATA_FD_MEMORY_LIMIT, 0);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
f = lseek(copy_fd, 0, SEEK_SET);
|
|
||||||
if (f != 0)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
if (r == 0) {
|
|
||||||
/* Did it fit into the limit? If so, we are done. */
|
|
||||||
r = memfd_set_sealed(copy_fd);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
return TAKE_FD(copy_fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hmm, pity, this didn't fit. Let's fall back to /tmp then, see below */
|
|
||||||
|
|
||||||
} else {
|
|
||||||
_cleanup_(close_pairp) int pipefds[2] = { -1, -1 };
|
|
||||||
int isz;
|
|
||||||
|
|
||||||
/* If memfds aren't available, use a pipe. Set O_NONBLOCK so that we will get EAGAIN rather
|
|
||||||
* then block indefinitely when we hit the pipe size limit */
|
|
||||||
|
|
||||||
if (pipe2(pipefds, O_CLOEXEC|O_NONBLOCK) < 0)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
|
|
||||||
if (isz < 0)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
/* Try to enlarge the pipe size if necessary */
|
|
||||||
if ((size_t) isz < DATA_FD_MEMORY_LIMIT) {
|
|
||||||
|
|
||||||
(void) fcntl(pipefds[1], F_SETPIPE_SZ, DATA_FD_MEMORY_LIMIT);
|
|
||||||
|
|
||||||
isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
|
|
||||||
if (isz < 0)
|
|
||||||
return -errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((size_t) isz >= DATA_FD_MEMORY_LIMIT) {
|
|
||||||
|
|
||||||
r = copy_bytes_full(fd, pipefds[1], DATA_FD_MEMORY_LIMIT, 0, &remains, &remains_size, NULL, NULL);
|
|
||||||
if (r < 0 && r != -EAGAIN)
|
|
||||||
return r; /* If we get EAGAIN it could be because of the source or because of
|
|
||||||
* the destination fd, we can't know, as sendfile() and friends won't
|
|
||||||
* tell us. Hence, treat this as reason to fall back, just to be
|
|
||||||
* sure. */
|
|
||||||
if (r == 0) {
|
|
||||||
/* Everything fit in, yay! */
|
|
||||||
(void) fd_nonblock(pipefds[0], false);
|
|
||||||
|
|
||||||
return TAKE_FD(pipefds[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Things didn't fit in. But we read data into the pipe, let's remember that, so that
|
|
||||||
* when writing the new file we incorporate this first. */
|
|
||||||
copy_fd = TAKE_FD(pipefds[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we have reason to believe this will fit fine in /tmp, then use that as first fallback. */
|
|
||||||
if ((!S_ISREG(st.st_mode) || st.st_size < DATA_FD_TMP_LIMIT) &&
|
|
||||||
(DATA_FD_MEMORY_LIMIT + remains_size) < DATA_FD_TMP_LIMIT) {
|
|
||||||
off_t f;
|
|
||||||
|
|
||||||
tmp_fd = open_tmpfile_unlinkable(NULL /* NULL as directory means /tmp */, O_RDWR|O_CLOEXEC);
|
|
||||||
if (tmp_fd < 0)
|
|
||||||
return tmp_fd;
|
|
||||||
|
|
||||||
if (copy_fd >= 0) {
|
|
||||||
/* If we tried a memfd/pipe first and it ended up being too large, then copy this into the
|
|
||||||
* temporary file first. */
|
|
||||||
|
|
||||||
r = copy_bytes(copy_fd, tmp_fd, UINT64_MAX, 0);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
assert(r == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remains_size > 0) {
|
|
||||||
/* If there were remaining bytes (i.e. read into memory, but not written out yet) from the
|
|
||||||
* failed copy operation, let's flush them out next. */
|
|
||||||
|
|
||||||
r = loop_write(tmp_fd, remains, remains_size, false);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = copy_bytes(fd, tmp_fd, DATA_FD_TMP_LIMIT - DATA_FD_MEMORY_LIMIT - remains_size, COPY_REFLINK);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
if (r == 0)
|
|
||||||
goto finish; /* Yay, it fit in */
|
|
||||||
|
|
||||||
/* It didn't fit in. Let's not forget to use what we already used */
|
|
||||||
f = lseek(tmp_fd, 0, SEEK_SET);
|
|
||||||
if (f != 0)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
CLOSE_AND_REPLACE(copy_fd, tmp_fd);
|
|
||||||
|
|
||||||
remains = mfree(remains);
|
|
||||||
remains_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* As last fallback use /var/tmp */
|
|
||||||
r = var_tmp_dir(&td);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
tmp_fd = open_tmpfile_unlinkable(td, O_RDWR|O_CLOEXEC);
|
|
||||||
if (tmp_fd < 0)
|
|
||||||
return tmp_fd;
|
|
||||||
|
|
||||||
if (copy_fd >= 0) {
|
|
||||||
/* If we tried a memfd/pipe first, or a file in /tmp, and it ended up being too large, than copy this
|
|
||||||
* into the temporary file first. */
|
|
||||||
r = copy_bytes(copy_fd, tmp_fd, UINT64_MAX, COPY_REFLINK);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
assert(r == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remains_size > 0) {
|
|
||||||
/* Then, copy in any read but not yet written bytes. */
|
|
||||||
r = loop_write(tmp_fd, remains, remains_size, false);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy in the rest */
|
|
||||||
r = copy_bytes(fd, tmp_fd, UINT64_MAX, COPY_REFLINK);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
assert(r == 0);
|
|
||||||
|
|
||||||
finish:
|
|
||||||
/* Now convert the O_RDWR file descriptor into an O_RDONLY one (and as side effect seek to the beginning of the
|
|
||||||
* file again */
|
|
||||||
|
|
||||||
return fd_reopen(tmp_fd, O_RDONLY|O_CLOEXEC);
|
|
||||||
}
|
|
||||||
|
|
||||||
int fd_move_above_stdio(int fd) {
|
int fd_move_above_stdio(int fd) {
|
||||||
int flags, copy;
|
int flags, copy;
|
||||||
PROTECT_ERRNO;
|
PROTECT_ERRNO;
|
||||||
@ -1057,3 +721,20 @@ int read_nr_open(void) {
|
|||||||
/* If we fail, fall back to the hard-coded kernel limit of 1024 * 1024. */
|
/* If we fail, fall back to the hard-coded kernel limit of 1024 * 1024. */
|
||||||
return 1024 * 1024;
|
return 1024 * 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is here because it's fd-related and is called from sd-journal code. Other btrfs-related utilities are
|
||||||
|
* in src/shared, but libsystemd must not link to libsystemd-shared, see docs/ARCHITECTURE.md. */
|
||||||
|
int btrfs_defrag_fd(int fd) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(fd >= 0);
|
||||||
|
|
||||||
|
r = fd_verify_regular(fd);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (ioctl(fd, BTRFS_IOC_DEFRAG, NULL) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@ -76,10 +76,6 @@ enum {
|
|||||||
ACQUIRE_NO_REGULAR = 1 << 4,
|
ACQUIRE_NO_REGULAR = 1 << 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
int acquire_data_fd(const void *data, size_t size, unsigned flags);
|
|
||||||
|
|
||||||
int fd_duplicate_data_fd(int fd);
|
|
||||||
|
|
||||||
int fd_move_above_stdio(int fd);
|
int fd_move_above_stdio(int fd);
|
||||||
|
|
||||||
int rearrange_stdio(int original_input_fd, int original_output_fd, int original_error_fd);
|
int rearrange_stdio(int original_input_fd, int original_output_fd, int original_error_fd);
|
||||||
@ -107,5 +103,5 @@ static inline int make_null_stdio(void) {
|
|||||||
|
|
||||||
|
|
||||||
int fd_reopen(int fd, int flags);
|
int fd_reopen(int fd, int flags);
|
||||||
|
|
||||||
int read_nr_open(void);
|
int read_nr_open(void);
|
||||||
|
int btrfs_defrag_fd(int fd);
|
||||||
|
|||||||
@ -8,7 +8,6 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "blockdev-util.h"
|
|
||||||
#include "dirent-util.h"
|
#include "dirent-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
@ -581,8 +580,6 @@ int get_files_in_directory(const char *path, char ***list) {
|
|||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
FOREACH_DIRENT_ALL(de, d, return -errno) {
|
FOREACH_DIRENT_ALL(de, d, return -errno) {
|
||||||
dirent_ensure_type(d, de);
|
|
||||||
|
|
||||||
if (!dirent_is_file(de))
|
if (!dirent_is_file(de))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1504,91 +1501,6 @@ int open_parent(const char *path, int flags, mode_t mode) {
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int blockdev_is_encrypted(const char *sysfs_path, unsigned depth_left) {
|
|
||||||
_cleanup_free_ char *p = NULL, *uuids = NULL;
|
|
||||||
_cleanup_closedir_ DIR *d = NULL;
|
|
||||||
int r, found_encrypted = false;
|
|
||||||
|
|
||||||
assert(sysfs_path);
|
|
||||||
|
|
||||||
if (depth_left == 0)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
p = path_join(sysfs_path, "dm/uuid");
|
|
||||||
if (!p)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
r = read_one_line_file(p, &uuids);
|
|
||||||
if (r != -ENOENT) {
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
/* The DM device's uuid attribute is prefixed with "CRYPT-" if this is a dm-crypt device. */
|
|
||||||
if (startswith(uuids, "CRYPT-"))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Not a dm-crypt device itself. But maybe it is on top of one? Follow the links in the "slaves/"
|
|
||||||
* subdir. */
|
|
||||||
|
|
||||||
p = mfree(p);
|
|
||||||
p = path_join(sysfs_path, "slaves");
|
|
||||||
if (!p)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
d = opendir(p);
|
|
||||||
if (!d) {
|
|
||||||
if (errno == ENOENT) /* Doesn't have underlying devices */
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return -errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
_cleanup_free_ char *q = NULL;
|
|
||||||
struct dirent *de;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
de = readdir_no_dot(d);
|
|
||||||
if (!de) {
|
|
||||||
if (errno != 0)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
break; /* No more underlying devices */
|
|
||||||
}
|
|
||||||
|
|
||||||
q = path_join(p, de->d_name);
|
|
||||||
if (!q)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
r = blockdev_is_encrypted(q, depth_left - 1);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
if (r == 0) /* we found one that is not encrypted? then propagate that immediately */
|
|
||||||
return false;
|
|
||||||
|
|
||||||
found_encrypted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return found_encrypted;
|
|
||||||
}
|
|
||||||
|
|
||||||
int path_is_encrypted(const char *path) {
|
|
||||||
char p[SYS_BLOCK_PATH_MAX(NULL)];
|
|
||||||
dev_t devt;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
r = get_block_device(path, &devt);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
if (r == 0) /* doesn't have a block device */
|
|
||||||
return false;
|
|
||||||
|
|
||||||
xsprintf_sys_block_path(p, NULL, devt);
|
|
||||||
|
|
||||||
return blockdev_is_encrypted(p, 10 /* safety net: maximum recursion depth */);
|
|
||||||
}
|
|
||||||
|
|
||||||
int conservative_renameat(
|
int conservative_renameat(
|
||||||
int olddirfd, const char *oldpath,
|
int olddirfd, const char *oldpath,
|
||||||
int newdirfd, const char *newpath) {
|
int newdirfd, const char *newpath) {
|
||||||
|
|||||||
@ -145,8 +145,6 @@ int syncfs_path(int atfd, const char *path);
|
|||||||
|
|
||||||
int open_parent(const char *path, int flags, mode_t mode);
|
int open_parent(const char *path, int flags, mode_t mode);
|
||||||
|
|
||||||
int path_is_encrypted(const char *path);
|
|
||||||
|
|
||||||
int conservative_renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
|
int conservative_renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
|
||||||
static inline int conservative_rename(const char *oldpath, const char *newpath) {
|
static inline int conservative_rename(const char *oldpath, const char *newpath) {
|
||||||
return conservative_renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath);
|
return conservative_renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath);
|
||||||
|
|||||||
@ -169,8 +169,6 @@ static int add_locales_from_libdir (Set *locales) {
|
|||||||
FOREACH_DIRENT(entry, dir, return -errno) {
|
FOREACH_DIRENT(entry, dir, return -errno) {
|
||||||
char *z;
|
char *z;
|
||||||
|
|
||||||
dirent_ensure_type(dir, entry);
|
|
||||||
|
|
||||||
if (entry->d_type != DT_DIR)
|
if (entry->d_type != DT_DIR)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@ -15,10 +15,6 @@ basic_sources = files('''
|
|||||||
async.h
|
async.h
|
||||||
audit-util.c
|
audit-util.c
|
||||||
audit-util.h
|
audit-util.h
|
||||||
blockdev-util.c
|
|
||||||
blockdev-util.h
|
|
||||||
btrfs-util.c
|
|
||||||
btrfs-util.h
|
|
||||||
build.c
|
build.c
|
||||||
build.h
|
build.h
|
||||||
bus-label.c
|
bus-label.c
|
||||||
@ -33,15 +29,11 @@ basic_sources = files('''
|
|||||||
chattr-util.h
|
chattr-util.h
|
||||||
conf-files.c
|
conf-files.c
|
||||||
conf-files.h
|
conf-files.h
|
||||||
copy.c
|
|
||||||
copy.h
|
|
||||||
creds-util.c
|
creds-util.c
|
||||||
creds-util.h
|
creds-util.h
|
||||||
def.h
|
def.h
|
||||||
dirent-util.c
|
dirent-util.c
|
||||||
dirent-util.h
|
dirent-util.h
|
||||||
dlfcn-util.c
|
|
||||||
dlfcn-util.h
|
|
||||||
dns-def.h
|
dns-def.h
|
||||||
efivars.c
|
efivars.c
|
||||||
efivars.h
|
efivars.h
|
||||||
@ -85,8 +77,6 @@ basic_sources = files('''
|
|||||||
ioprio.h
|
ioprio.h
|
||||||
khash.c
|
khash.c
|
||||||
khash.h
|
khash.h
|
||||||
label.c
|
|
||||||
label.h
|
|
||||||
limits-util.c
|
limits-util.c
|
||||||
limits-util.h
|
limits-util.h
|
||||||
linux/btrfs.h
|
linux/btrfs.h
|
||||||
@ -157,7 +147,6 @@ basic_sources = files('''
|
|||||||
missing_syscall.h
|
missing_syscall.h
|
||||||
missing_timerfd.h
|
missing_timerfd.h
|
||||||
missing_type.h
|
missing_type.h
|
||||||
mkdir-label.c
|
|
||||||
mkdir.c
|
mkdir.c
|
||||||
mkdir.h
|
mkdir.h
|
||||||
mountpoint-util.c
|
mountpoint-util.c
|
||||||
@ -188,8 +177,6 @@ basic_sources = files('''
|
|||||||
procfs-util.c
|
procfs-util.c
|
||||||
procfs-util.h
|
procfs-util.h
|
||||||
pthread-util.h
|
pthread-util.h
|
||||||
quota-util.c
|
|
||||||
quota-util.h
|
|
||||||
random-util.c
|
random-util.c
|
||||||
random-util.h
|
random-util.h
|
||||||
ratelimit.c
|
ratelimit.c
|
||||||
@ -202,10 +189,6 @@ basic_sources = files('''
|
|||||||
replace-var.h
|
replace-var.h
|
||||||
rlimit-util.c
|
rlimit-util.c
|
||||||
rlimit-util.h
|
rlimit-util.h
|
||||||
rm-rf.c
|
|
||||||
rm-rf.h
|
|
||||||
selinux-util.c
|
|
||||||
selinux-util.h
|
|
||||||
set.h
|
set.h
|
||||||
sigbus.c
|
sigbus.c
|
||||||
sigbus.h
|
sigbus.h
|
||||||
@ -213,9 +196,6 @@ basic_sources = files('''
|
|||||||
signal-util.h
|
signal-util.h
|
||||||
siphash24.c
|
siphash24.c
|
||||||
siphash24.h
|
siphash24.h
|
||||||
smack-util.c
|
|
||||||
smack-util.h
|
|
||||||
socket-label.c
|
|
||||||
socket-util.c
|
socket-util.c
|
||||||
socket-util.h
|
socket-util.h
|
||||||
sort-util.c
|
sort-util.c
|
||||||
@ -394,10 +374,7 @@ libbasic = static_library(
|
|||||||
dependencies : [versiondep,
|
dependencies : [versiondep,
|
||||||
threads,
|
threads,
|
||||||
libcap,
|
libcap,
|
||||||
libseccomp,
|
libm],
|
||||||
libselinux,
|
|
||||||
libm,
|
|
||||||
libdl],
|
|
||||||
c_args : ['-fvisibility=default'],
|
c_args : ['-fvisibility=default'],
|
||||||
install : false)
|
install : false)
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,6 @@
|
|||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "fs-util.h"
|
#include "fs-util.h"
|
||||||
#include "label.h"
|
|
||||||
#include "missing_stat.h"
|
#include "missing_stat.h"
|
||||||
#include "missing_syscall.h"
|
#include "missing_syscall.h"
|
||||||
#include "mkdir.h"
|
#include "mkdir.h"
|
||||||
@ -510,25 +509,3 @@ int mount_propagation_flags_from_string(const char *name, unsigned long *ret) {
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int make_mount_point_inode_from_stat(const struct stat *st, const char *dest, mode_t mode) {
|
|
||||||
assert(st);
|
|
||||||
assert(dest);
|
|
||||||
|
|
||||||
if (S_ISDIR(st->st_mode))
|
|
||||||
return mkdir_label(dest, mode);
|
|
||||||
else
|
|
||||||
return mknod(dest, S_IFREG|(mode & ~0111), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int make_mount_point_inode_from_path(const char *source, const char *dest, mode_t mode) {
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
assert(source);
|
|
||||||
assert(dest);
|
|
||||||
|
|
||||||
if (stat(source, &st) < 0)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
return make_mount_point_inode_from_stat(&st, dest, mode);
|
|
||||||
}
|
|
||||||
|
|||||||
@ -23,7 +23,3 @@ int dev_is_devtmpfs(void);
|
|||||||
|
|
||||||
const char *mount_propagation_flags_to_string(unsigned long flags);
|
const char *mount_propagation_flags_to_string(unsigned long flags);
|
||||||
int mount_propagation_flags_from_string(const char *name, unsigned long *ret);
|
int mount_propagation_flags_from_string(const char *name, unsigned long *ret);
|
||||||
|
|
||||||
/* Creates a mount point (not parents) based on the source path or stat - ie, a file or a directory */
|
|
||||||
int make_mount_point_inode_from_stat(const struct stat *st, const char *dest, mode_t mode);
|
|
||||||
int make_mount_point_inode_from_path(const char *source, const char *dest, mode_t mode);
|
|
||||||
|
|||||||
@ -21,7 +21,6 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "copy.h"
|
|
||||||
#include "def.h"
|
#include "def.h"
|
||||||
#include "env-util.h"
|
#include "env-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
|
|||||||
@ -321,7 +321,6 @@ int unit_file_build_name_map(
|
|||||||
if (hashmap_contains(ids, de->d_name))
|
if (hashmap_contains(ids, de->d_name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
dirent_ensure_type(d, de);
|
|
||||||
if (de->d_type == DT_LNK) {
|
if (de->d_type == DT_LNK) {
|
||||||
/* We don't explicitly check for alias loops here. unit_ids_map_get() which
|
/* We don't explicitly check for alias loops here. unit_ids_map_get() which
|
||||||
* limits the number of hops should be used to access the map. */
|
* limits the number of hops should be used to access the map. */
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
#include "bus-common-errors.h"
|
#include "bus-common-errors.h"
|
||||||
#include "bus-get-properties.h"
|
#include "bus-get-properties.h"
|
||||||
#include "bus-log-control-api.h"
|
#include "bus-log-control-api.h"
|
||||||
|
#include "data-fd-util.h"
|
||||||
#include "dbus-cgroup.h"
|
#include "dbus-cgroup.h"
|
||||||
#include "dbus-execute.h"
|
#include "dbus-execute.h"
|
||||||
#include "dbus-job.h"
|
#include "dbus-job.h"
|
||||||
|
|||||||
@ -46,6 +46,7 @@
|
|||||||
#include "cgroup-setup.h"
|
#include "cgroup-setup.h"
|
||||||
#include "chown-recursive.h"
|
#include "chown-recursive.h"
|
||||||
#include "cpu-set-util.h"
|
#include "cpu-set-util.h"
|
||||||
|
#include "data-fd-util.h"
|
||||||
#include "def.h"
|
#include "def.h"
|
||||||
#include "env-file.h"
|
#include "env-file.h"
|
||||||
#include "env-util.h"
|
#include "env-util.h"
|
||||||
|
|||||||
@ -4512,15 +4512,13 @@ void manager_status_printf(Manager *m, StatusType type, const char *status, cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
Set* manager_get_units_requiring_mounts_for(Manager *m, const char *path) {
|
Set* manager_get_units_requiring_mounts_for(Manager *m, const char *path) {
|
||||||
char p[strlen(path)+1];
|
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
assert(path);
|
assert(path);
|
||||||
|
|
||||||
strcpy(p, path);
|
if (path_equal(path, "/"))
|
||||||
path_simplify(p);
|
path = "";
|
||||||
|
|
||||||
return hashmap_get(m->units_requiring_mounts_for, streq(p, "/") ? "" : p);
|
return hashmap_get(m->units_requiring_mounts_for, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
int manager_update_failed_units(Manager *m, Unit *u, bool failed) {
|
int manager_update_failed_units(Manager *m, Unit *u, bool failed) {
|
||||||
|
|||||||
@ -82,7 +82,6 @@ static int write_access2_rules(const char *srcdir) {
|
|||||||
FOREACH_DIRENT(entry, dir, return 0) {
|
FOREACH_DIRENT(entry, dir, return 0) {
|
||||||
_cleanup_fclose_ FILE *policy = NULL;
|
_cleanup_fclose_ FILE *policy = NULL;
|
||||||
|
|
||||||
dirent_ensure_type(dir, entry);
|
|
||||||
if (!dirent_is_file(entry))
|
if (!dirent_is_file(entry))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -149,7 +148,6 @@ static int write_cipso2_rules(const char *srcdir) {
|
|||||||
FOREACH_DIRENT(entry, dir, return 0) {
|
FOREACH_DIRENT(entry, dir, return 0) {
|
||||||
_cleanup_fclose_ FILE *policy = NULL;
|
_cleanup_fclose_ FILE *policy = NULL;
|
||||||
|
|
||||||
dirent_ensure_type(dir, entry);
|
|
||||||
if (!dirent_is_file(entry))
|
if (!dirent_is_file(entry))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@ -4562,45 +4562,43 @@ int unit_kill_context(
|
|||||||
}
|
}
|
||||||
|
|
||||||
int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask) {
|
int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask) {
|
||||||
_cleanup_free_ char *p = NULL;
|
|
||||||
UnitDependencyInfo di;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(u);
|
assert(u);
|
||||||
assert(path);
|
assert(path);
|
||||||
|
|
||||||
/* Registers a unit for requiring a certain path and all its prefixes. We keep a hashtable of these paths in
|
/* Registers a unit for requiring a certain path and all its prefixes. We keep a hashtable of these
|
||||||
* the unit (from the path to the UnitDependencyInfo structure indicating how to the dependency came to
|
* paths in the unit (from the path to the UnitDependencyInfo structure indicating how to the
|
||||||
* be). However, we build a prefix table for all possible prefixes so that new appearing mount units can easily
|
* dependency came to be). However, we build a prefix table for all possible prefixes so that new
|
||||||
* determine which units to make themselves a dependency of. */
|
* appearing mount units can easily determine which units to make themselves a dependency of. */
|
||||||
|
|
||||||
if (!path_is_absolute(path))
|
if (!path_is_absolute(path))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
r = hashmap_ensure_allocated(&u->requires_mounts_for, &path_hash_ops);
|
if (hashmap_contains(u->requires_mounts_for, path)) /* Exit quickly if the path is already covered. */
|
||||||
if (r < 0)
|
return 0;
|
||||||
return r;
|
|
||||||
|
|
||||||
p = strdup(path);
|
_cleanup_free_ char *p = strdup(path);
|
||||||
if (!p)
|
if (!p)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* Use the canonical form of the path as the stored key. We call path_is_normalized()
|
||||||
|
* only after simplification, since path_is_normalized() rejects paths with '.'.
|
||||||
|
* path_is_normalized() also verifies that the path fits in PATH_MAX. */
|
||||||
path = path_simplify(p);
|
path = path_simplify(p);
|
||||||
|
|
||||||
if (!path_is_normalized(path))
|
if (!path_is_normalized(path))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
if (hashmap_contains(u->requires_mounts_for, path))
|
UnitDependencyInfo di = {
|
||||||
return 0;
|
|
||||||
|
|
||||||
di = (UnitDependencyInfo) {
|
|
||||||
.origin_mask = mask
|
.origin_mask = mask
|
||||||
};
|
};
|
||||||
|
|
||||||
r = hashmap_put(u->requires_mounts_for, path, di.data);
|
r = hashmap_ensure_put(&u->requires_mounts_for, &path_hash_ops, p, di.data);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
p = NULL;
|
assert(r > 0);
|
||||||
|
TAKE_PTR(p); /* path remains a valid pointer to the string stored in the hashmap */
|
||||||
|
|
||||||
char prefix[strlen(path) + 1];
|
char prefix[strlen(path) + 1];
|
||||||
PATH_FOREACH_PREFIX_MORE(prefix, path) {
|
PATH_FOREACH_PREFIX_MORE(prefix, path) {
|
||||||
|
|||||||
@ -311,8 +311,6 @@ static int enumerate_dir(
|
|||||||
}
|
}
|
||||||
|
|
||||||
FOREACH_DIRENT_ALL(de, d, return -errno) {
|
FOREACH_DIRENT_ALL(de, d, return -errno) {
|
||||||
dirent_ensure_type(d, de);
|
|
||||||
|
|
||||||
if (dropins && de->d_type == DT_DIR && endswith(de->d_name, ".d")) {
|
if (dropins && de->d_type == DT_DIR && endswith(de->d_name, ".d")) {
|
||||||
if (!GREEDY_REALLOC0(dirs, n_dirs + 2))
|
if (!GREEDY_REALLOC0(dirs, n_dirs + 2))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
#include "blockdev-util.h"
|
#include "blockdev-util.h"
|
||||||
#include "btrfs-util.h"
|
#include "btrfs-util.h"
|
||||||
#include "bus-common-errors.h"
|
#include "bus-common-errors.h"
|
||||||
|
#include "data-fd-util.h"
|
||||||
#include "env-util.h"
|
#include "env-util.h"
|
||||||
#include "errno-list.h"
|
#include "errno-list.h"
|
||||||
#include "errno-util.h"
|
#include "errno-util.h"
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
|
|
||||||
|
#include "blockdev-util.h"
|
||||||
#include "chown-recursive.h"
|
#include "chown-recursive.h"
|
||||||
#include "copy.h"
|
#include "copy.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
#include "alloc-util.h"
|
|
||||||
#include "dlfcn-util.h"
|
#include "dlfcn-util.h"
|
||||||
|
#include "log.h"
|
||||||
#include "pcre2-dlopen.h"
|
#include "pcre2-dlopen.h"
|
||||||
|
|
||||||
#if HAVE_PCRE2
|
#if HAVE_PCRE2
|
||||||
@ -16,17 +16,6 @@ int (*sym_pcre2_match)(const pcre2_code *, PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, u
|
|||||||
PCRE2_SIZE* (*sym_pcre2_get_ovector_pointer)(pcre2_match_data *);
|
PCRE2_SIZE* (*sym_pcre2_get_ovector_pointer)(pcre2_match_data *);
|
||||||
|
|
||||||
int dlopen_pcre2(void) {
|
int dlopen_pcre2(void) {
|
||||||
_cleanup_(dlclosep) void *dl = NULL;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
if (pcre2_dl)
|
|
||||||
return 0; /* Already loaded */
|
|
||||||
|
|
||||||
dl = dlopen("libpcre2-8.so.0", RTLD_LAZY);
|
|
||||||
if (!dl)
|
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
|
||||||
"PCRE2 support is not installed: %s", dlerror());
|
|
||||||
|
|
||||||
/* So here's something weird: PCRE2 actually renames the symbols exported by the library via C
|
/* So here's something weird: PCRE2 actually renames the symbols exported by the library via C
|
||||||
* macros, so that the exported symbols carry a suffix "_8" but when used from C the suffix is
|
* macros, so that the exported symbols carry a suffix "_8" but when used from C the suffix is
|
||||||
* gone. In the argument list below we ignore this mangling. Surprisingly (at least to me), we
|
* gone. In the argument list below we ignore this mangling. Surprisingly (at least to me), we
|
||||||
@ -35,25 +24,15 @@ int dlopen_pcre2(void) {
|
|||||||
* string actually contains the "_8" suffix already due to that and we don't have to append it
|
* string actually contains the "_8" suffix already due to that and we don't have to append it
|
||||||
* manually anymore. C is weird. 🤯 */
|
* manually anymore. C is weird. 🤯 */
|
||||||
|
|
||||||
r = dlsym_many_and_warn(
|
return dlopen_many_sym_or_warn(
|
||||||
dl,
|
&pcre2_dl, "libpcre2-8.so.0", LOG_ERR,
|
||||||
LOG_ERR,
|
|
||||||
DLSYM_ARG(pcre2_match_data_create),
|
DLSYM_ARG(pcre2_match_data_create),
|
||||||
DLSYM_ARG(pcre2_match_data_free),
|
DLSYM_ARG(pcre2_match_data_free),
|
||||||
DLSYM_ARG(pcre2_code_free),
|
DLSYM_ARG(pcre2_code_free),
|
||||||
DLSYM_ARG(pcre2_compile),
|
DLSYM_ARG(pcre2_compile),
|
||||||
DLSYM_ARG(pcre2_get_error_message),
|
DLSYM_ARG(pcre2_get_error_message),
|
||||||
DLSYM_ARG(pcre2_match),
|
DLSYM_ARG(pcre2_match),
|
||||||
DLSYM_ARG(pcre2_get_ovector_pointer),
|
DLSYM_ARG(pcre2_get_ovector_pointer));
|
||||||
NULL);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
/* Note that we never release the reference here, because there's no real reason to, after all this
|
|
||||||
* was traditionally a regular shared library dependency which lives forever too. */
|
|
||||||
pcre2_dl = TAKE_PTR(dl);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|||||||
@ -131,8 +131,6 @@ libsystemd_sources = files('''
|
|||||||
sd-device/device-util.h
|
sd-device/device-util.h
|
||||||
sd-device/sd-device.c
|
sd-device/sd-device.c
|
||||||
sd-hwdb/hwdb-internal.h
|
sd-hwdb/hwdb-internal.h
|
||||||
sd-hwdb/hwdb-util.c
|
|
||||||
sd-hwdb/hwdb-util.h
|
|
||||||
sd-hwdb/sd-hwdb.c
|
sd-hwdb/sd-hwdb.c
|
||||||
sd-netlink/generic-netlink.c
|
sd-netlink/generic-netlink.c
|
||||||
sd-netlink/generic-netlink.h
|
sd-netlink/generic-netlink.h
|
||||||
|
|||||||
@ -22,7 +22,6 @@
|
|||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "rlimit-util.h"
|
#include "rlimit-util.h"
|
||||||
#include "selinux-util.h"
|
|
||||||
#include "signal-util.h"
|
#include "signal-util.h"
|
||||||
#include "stdio-util.h"
|
#include "stdio-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
|
|||||||
@ -3,10 +3,27 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "def.h"
|
||||||
|
#include "hashmap.h"
|
||||||
#include "sparse-endian.h"
|
#include "sparse-endian.h"
|
||||||
|
|
||||||
#define HWDB_SIG { 'K', 'S', 'L', 'P', 'H', 'H', 'R', 'H' }
|
#define HWDB_SIG { 'K', 'S', 'L', 'P', 'H', 'H', 'R', 'H' }
|
||||||
|
|
||||||
|
struct sd_hwdb {
|
||||||
|
unsigned n_ref;
|
||||||
|
|
||||||
|
FILE *f;
|
||||||
|
struct stat st;
|
||||||
|
union {
|
||||||
|
struct trie_header_f *head;
|
||||||
|
const char *map;
|
||||||
|
};
|
||||||
|
|
||||||
|
OrderedHashmap *properties;
|
||||||
|
Iterator properties_iterator;
|
||||||
|
bool properties_modified;
|
||||||
|
};
|
||||||
|
|
||||||
/* on-disk trie objects */
|
/* on-disk trie objects */
|
||||||
struct trie_header_f {
|
struct trie_header_f {
|
||||||
uint8_t signature[8];
|
uint8_t signature[8];
|
||||||
@ -63,3 +80,10 @@ struct trie_value_entry2_f {
|
|||||||
le16_t file_priority;
|
le16_t file_priority;
|
||||||
le16_t padding;
|
le16_t padding;
|
||||||
} _packed_;
|
} _packed_;
|
||||||
|
|
||||||
|
#define hwdb_bin_paths \
|
||||||
|
"/etc/systemd/hwdb/hwdb.bin\0" \
|
||||||
|
"/etc/udev/hwdb.bin\0" \
|
||||||
|
"/usr/lib/systemd/hwdb/hwdb.bin\0" \
|
||||||
|
_CONF_PATHS_SPLIT_USR_NULSTR("systemd/hwdb/hwdb.bin") \
|
||||||
|
UDEVLIBEXECDIR "/hwdb.bin\0"
|
||||||
|
|||||||
@ -17,26 +17,10 @@
|
|||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
#include "hwdb-internal.h"
|
#include "hwdb-internal.h"
|
||||||
#include "hwdb-util.h"
|
|
||||||
#include "nulstr-util.h"
|
#include "nulstr-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "time-util.h"
|
#include "time-util.h"
|
||||||
|
|
||||||
struct sd_hwdb {
|
|
||||||
unsigned n_ref;
|
|
||||||
|
|
||||||
FILE *f;
|
|
||||||
struct stat st;
|
|
||||||
union {
|
|
||||||
struct trie_header_f *head;
|
|
||||||
const char *map;
|
|
||||||
};
|
|
||||||
|
|
||||||
OrderedHashmap *properties;
|
|
||||||
Iterator properties_iterator;
|
|
||||||
bool properties_modified;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct linebuf {
|
struct linebuf {
|
||||||
char bytes[LINE_MAX];
|
char bytes[LINE_MAX];
|
||||||
size_t size;
|
size_t size;
|
||||||
@ -296,15 +280,6 @@ static int trie_search_f(sd_hwdb *hwdb, const char *search) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char hwdb_bin_paths[] =
|
|
||||||
"/etc/systemd/hwdb/hwdb.bin\0"
|
|
||||||
"/etc/udev/hwdb.bin\0"
|
|
||||||
"/usr/lib/systemd/hwdb/hwdb.bin\0"
|
|
||||||
#if HAVE_SPLIT_USR
|
|
||||||
"/lib/systemd/hwdb/hwdb.bin\0"
|
|
||||||
#endif
|
|
||||||
UDEVLIBEXECDIR "/hwdb.bin\0";
|
|
||||||
|
|
||||||
_public_ int sd_hwdb_new(sd_hwdb **ret) {
|
_public_ int sd_hwdb_new(sd_hwdb **ret) {
|
||||||
_cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
|
_cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
|
||||||
const char *hwdb_bin_path;
|
const char *hwdb_bin_path;
|
||||||
@ -372,30 +347,6 @@ static sd_hwdb *hwdb_free(sd_hwdb *hwdb) {
|
|||||||
|
|
||||||
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_hwdb, sd_hwdb, hwdb_free)
|
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_hwdb, sd_hwdb, hwdb_free)
|
||||||
|
|
||||||
bool hwdb_validate(sd_hwdb *hwdb) {
|
|
||||||
bool found = false;
|
|
||||||
const char* p;
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
if (!hwdb)
|
|
||||||
return false;
|
|
||||||
if (!hwdb->f)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* if hwdb.bin doesn't exist anywhere, we need to update */
|
|
||||||
NULSTR_FOREACH(p, hwdb_bin_paths)
|
|
||||||
if (stat(p, &st) >= 0) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!found)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (timespec_load(&hwdb->st.st_mtim) != timespec_load(&st.st_mtim))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int properties_prepare(sd_hwdb *hwdb, const char *modalias) {
|
static int properties_prepare(sd_hwdb *hwdb, const char *modalias) {
|
||||||
assert(hwdb);
|
assert(hwdb);
|
||||||
assert(modalias);
|
assert(modalias);
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
#include <linux/magic.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
@ -13,7 +14,6 @@
|
|||||||
#include "sd-event.h"
|
#include "sd-event.h"
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "btrfs-util.h"
|
|
||||||
#include "chattr-util.h"
|
#include "chattr-util.h"
|
||||||
#include "compress.h"
|
#include "compress.h"
|
||||||
#include "env-util.h"
|
#include "env-util.h"
|
||||||
@ -3379,7 +3379,7 @@ static int journal_file_warn_btrfs(JournalFile *f) {
|
|||||||
* expense of data integrity features (which shouldn't be too
|
* expense of data integrity features (which shouldn't be too
|
||||||
* bad, given that we do our own checksumming). */
|
* bad, given that we do our own checksumming). */
|
||||||
|
|
||||||
r = btrfs_is_filesystem(f->fd);
|
r = fd_is_fs_type(f->fd, BTRFS_SUPER_MAGIC);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_warning_errno(r, "Failed to determine if journal is on btrfs: %m");
|
return log_warning_errno(r, "Failed to determine if journal is on btrfs: %m");
|
||||||
if (!r)
|
if (!r)
|
||||||
|
|||||||
@ -170,7 +170,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
|
|||||||
h2 = journal_file_hash_data(f, o->data.payload, le64toh(o->object.size) - offsetof(Object, data.payload));
|
h2 = journal_file_hash_data(f, o->data.payload, le64toh(o->object.size) - offsetof(Object, data.payload));
|
||||||
|
|
||||||
if (h1 != h2) {
|
if (h1 != h2) {
|
||||||
error(offset, "Invalid hash (%08"PRIx64" vs. %08"PRIx64, h1, h2);
|
error(offset, "Invalid hash (%08" PRIx64 " vs. %08" PRIx64 ")", h1, h2);
|
||||||
return -EBADMSG;
|
return -EBADMSG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -795,8 +795,6 @@ _public_ int sd_get_uids(uid_t **users) {
|
|||||||
int k;
|
int k;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
|
|
||||||
dirent_ensure_type(d, de);
|
|
||||||
|
|
||||||
if (!dirent_is_file(de))
|
if (!dirent_is_file(de))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@ -1374,7 +1374,6 @@ static int flush_devices(Manager *m) {
|
|||||||
struct dirent *de;
|
struct dirent *de;
|
||||||
|
|
||||||
FOREACH_DIRENT_ALL(de, d, break) {
|
FOREACH_DIRENT_ALL(de, d, break) {
|
||||||
dirent_ensure_type(d, de);
|
|
||||||
if (!dirent_is_file(de))
|
if (!dirent_is_file(de))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@ -299,7 +299,6 @@ static int manager_enumerate_linger_users(Manager *m) {
|
|||||||
FOREACH_DIRENT(de, d, return -errno) {
|
FOREACH_DIRENT(de, d, return -errno) {
|
||||||
int k;
|
int k;
|
||||||
|
|
||||||
dirent_ensure_type(d, de);
|
|
||||||
if (!dirent_is_file(de))
|
if (!dirent_is_file(de))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@ -787,8 +787,6 @@ static int find_loop_device(const char *backing_file, char **loop_dev) {
|
|||||||
_cleanup_free_ char *sys = NULL, *fname = NULL;
|
_cleanup_free_ char *sys = NULL, *fname = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
dirent_ensure_type(d, de);
|
|
||||||
|
|
||||||
if (de->d_type != DT_DIR)
|
if (de->d_type != DT_DIR)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "bus-common-errors.h"
|
#include "bus-common-errors.h"
|
||||||
#include "bus-polkit.h"
|
#include "bus-polkit.h"
|
||||||
|
#include "data-fd-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "oomd-manager-bus.h"
|
#include "oomd-manager-bus.h"
|
||||||
#include "oomd-manager.h"
|
#include "oomd-manager.h"
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
#include "bus-error.h"
|
#include "bus-error.h"
|
||||||
#include "conf-files.h"
|
#include "conf-files.h"
|
||||||
#include "copy.h"
|
#include "copy.h"
|
||||||
|
#include "data-fd-util.h"
|
||||||
#include "def.h"
|
#include "def.h"
|
||||||
#include "dirent-util.h"
|
#include "dirent-util.h"
|
||||||
#include "discover-image.h"
|
#include "discover-image.h"
|
||||||
@ -153,7 +154,7 @@ static int send_item(
|
|||||||
assert(name);
|
assert(name);
|
||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
|
|
||||||
data_fd = fd_duplicate_data_fd(fd);
|
data_fd = copy_data_fd(fd);
|
||||||
if (data_fd < 0)
|
if (data_fd < 0)
|
||||||
return data_fd;
|
return data_fd;
|
||||||
|
|
||||||
@ -311,7 +312,6 @@ static int extract_now(
|
|||||||
if (hashmap_get(unit_files, de->d_name))
|
if (hashmap_get(unit_files, de->d_name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
dirent_ensure_type(d, de);
|
|
||||||
if (!IN_SET(de->d_type, DT_LNK, DT_REG))
|
if (!IN_SET(de->d_type, DT_LNK, DT_REG))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1396,7 +1396,6 @@ int portable_detach(
|
|||||||
if (set_contains(unit_files, de->d_name))
|
if (set_contains(unit_files, de->d_name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
dirent_ensure_type(d, de);
|
|
||||||
if (!IN_SET(de->d_type, DT_LNK, DT_REG))
|
if (!IN_SET(de->d_type, DT_LNK, DT_REG))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1569,7 +1568,6 @@ static int portable_get_state_internal(
|
|||||||
if (set_contains(unit_files, de->d_name))
|
if (set_contains(unit_files, de->d_name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
dirent_ensure_type(d, de);
|
|
||||||
if (!IN_SET(de->d_type, DT_LNK, DT_REG))
|
if (!IN_SET(de->d_type, DT_LNK, DT_REG))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@ -256,3 +256,88 @@ int blockdev_partscan_enabled(int fd) {
|
|||||||
|
|
||||||
return !FLAGS_SET(ull, GENHD_FL_NO_PART_SCAN);
|
return !FLAGS_SET(ull, GENHD_FL_NO_PART_SCAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int blockdev_is_encrypted(const char *sysfs_path, unsigned depth_left) {
|
||||||
|
_cleanup_free_ char *p = NULL, *uuids = NULL;
|
||||||
|
_cleanup_closedir_ DIR *d = NULL;
|
||||||
|
int r, found_encrypted = false;
|
||||||
|
|
||||||
|
assert(sysfs_path);
|
||||||
|
|
||||||
|
if (depth_left == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
p = path_join(sysfs_path, "dm/uuid");
|
||||||
|
if (!p)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
r = read_one_line_file(p, &uuids);
|
||||||
|
if (r != -ENOENT) {
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
/* The DM device's uuid attribute is prefixed with "CRYPT-" if this is a dm-crypt device. */
|
||||||
|
if (startswith(uuids, "CRYPT-"))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not a dm-crypt device itself. But maybe it is on top of one? Follow the links in the "slaves/"
|
||||||
|
* subdir. */
|
||||||
|
|
||||||
|
p = mfree(p);
|
||||||
|
p = path_join(sysfs_path, "slaves");
|
||||||
|
if (!p)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
d = opendir(p);
|
||||||
|
if (!d) {
|
||||||
|
if (errno == ENOENT) /* Doesn't have underlying devices */
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
_cleanup_free_ char *q = NULL;
|
||||||
|
struct dirent *de;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
de = readdir_no_dot(d);
|
||||||
|
if (!de) {
|
||||||
|
if (errno != 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
break; /* No more underlying devices */
|
||||||
|
}
|
||||||
|
|
||||||
|
q = path_join(p, de->d_name);
|
||||||
|
if (!q)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
r = blockdev_is_encrypted(q, depth_left - 1);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (r == 0) /* we found one that is not encrypted? then propagate that immediately */
|
||||||
|
return false;
|
||||||
|
|
||||||
|
found_encrypted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return found_encrypted;
|
||||||
|
}
|
||||||
|
|
||||||
|
int path_is_encrypted(const char *path) {
|
||||||
|
char p[SYS_BLOCK_PATH_MAX(NULL)];
|
||||||
|
dev_t devt;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = get_block_device(path, &devt);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (r == 0) /* doesn't have a block device */
|
||||||
|
return false;
|
||||||
|
|
||||||
|
xsprintf_sys_block_path(p, NULL, devt);
|
||||||
|
|
||||||
|
return blockdev_is_encrypted(p, 10 /* safety net: maximum recursion depth */);
|
||||||
|
}
|
||||||
@ -22,3 +22,5 @@ int get_block_device_harder(const char *path, dev_t *dev);
|
|||||||
int lock_whole_block_device(dev_t devt, int operation);
|
int lock_whole_block_device(dev_t devt, int operation);
|
||||||
|
|
||||||
int blockdev_partscan_enabled(int fd);
|
int blockdev_partscan_enabled(int fd);
|
||||||
|
|
||||||
|
int path_is_encrypted(const char *path);
|
||||||
@ -482,7 +482,6 @@ static int boot_entries_find_unified(
|
|||||||
_cleanup_free_ char *j = NULL, *osrelease = NULL, *cmdline = NULL;
|
_cleanup_free_ char *j = NULL, *osrelease = NULL, *cmdline = NULL;
|
||||||
_cleanup_close_ int fd = -1;
|
_cleanup_close_ int fd = -1;
|
||||||
|
|
||||||
dirent_ensure_type(d, de);
|
|
||||||
if (!dirent_is_file(de))
|
if (!dirent_is_file(de))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
#include "alloc-util.h"
|
|
||||||
#include "dlfcn-util.h"
|
#include "dlfcn-util.h"
|
||||||
#include "bpf-dlopen.h"
|
#include "bpf-dlopen.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#if HAVE_LIBBPF
|
#if HAVE_LIBBPF
|
||||||
static void *bpf_dl = NULL;
|
static void *bpf_dl = NULL;
|
||||||
@ -24,20 +24,8 @@ bool (*sym_bpf_probe_prog_type)(enum bpf_prog_type, __u32);
|
|||||||
const char* (*sym_bpf_program__name)(const struct bpf_program *);
|
const char* (*sym_bpf_program__name)(const struct bpf_program *);
|
||||||
|
|
||||||
int dlopen_bpf(void) {
|
int dlopen_bpf(void) {
|
||||||
_cleanup_(dlclosep) void *dl = NULL;
|
return dlopen_many_sym_or_warn(
|
||||||
int r;
|
&bpf_dl, "libbpf.so.0", LOG_DEBUG,
|
||||||
|
|
||||||
if (bpf_dl)
|
|
||||||
return 0; /* Already loaded */
|
|
||||||
|
|
||||||
dl = dlopen("libbpf.so.0", RTLD_LAZY);
|
|
||||||
if (!dl)
|
|
||||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
|
||||||
"libbpf is not installed: %s", dlerror());
|
|
||||||
|
|
||||||
r = dlsym_many_and_warn(
|
|
||||||
dl,
|
|
||||||
LOG_DEBUG,
|
|
||||||
DLSYM_ARG(bpf_link__destroy),
|
DLSYM_ARG(bpf_link__destroy),
|
||||||
DLSYM_ARG(bpf_link__fd),
|
DLSYM_ARG(bpf_link__fd),
|
||||||
DLSYM_ARG(bpf_map__fd),
|
DLSYM_ARG(bpf_map__fd),
|
||||||
@ -52,15 +40,7 @@ int dlopen_bpf(void) {
|
|||||||
DLSYM_ARG(bpf_probe_prog_type),
|
DLSYM_ARG(bpf_probe_prog_type),
|
||||||
DLSYM_ARG(bpf_program__attach_cgroup),
|
DLSYM_ARG(bpf_program__attach_cgroup),
|
||||||
DLSYM_ARG(bpf_program__name),
|
DLSYM_ARG(bpf_program__name),
|
||||||
DLSYM_ARG(libbpf_get_error),
|
DLSYM_ARG(libbpf_get_error));
|
||||||
NULL);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
/* Note that we never release the reference here, because there's no real reason to, after all this
|
|
||||||
* was traditionally a regular shared library dependency which lives forever too. */
|
|
||||||
bpf_dl = TAKE_PTR(dl);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|||||||
@ -69,17 +69,6 @@ static int extract_subvolume_name(const char *path, const char **subvolume) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_is_filesystem(int fd) {
|
|
||||||
struct statfs sfs;
|
|
||||||
|
|
||||||
assert(fd >= 0);
|
|
||||||
|
|
||||||
if (fstatfs(fd, &sfs) < 0)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
return F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
int btrfs_is_subvol_fd(int fd) {
|
int btrfs_is_subvol_fd(int fd) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
@ -93,7 +82,7 @@ int btrfs_is_subvol_fd(int fd) {
|
|||||||
if (!btrfs_might_be_subvol(&st))
|
if (!btrfs_might_be_subvol(&st))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return btrfs_is_filesystem(fd);
|
return fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_is_subvol(const char *path) {
|
int btrfs_is_subvol(const char *path) {
|
||||||
@ -286,7 +275,7 @@ int btrfs_get_block_device_fd(int fd, dev_t *dev) {
|
|||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
assert(dev);
|
assert(dev);
|
||||||
|
|
||||||
r = btrfs_is_filesystem(fd);
|
r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (!r)
|
if (!r)
|
||||||
@ -361,7 +350,7 @@ int btrfs_subvol_get_id_fd(int fd, uint64_t *ret) {
|
|||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
assert(ret);
|
assert(ret);
|
||||||
|
|
||||||
r = btrfs_is_filesystem(fd);
|
r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (!r)
|
if (!r)
|
||||||
@ -481,7 +470,7 @@ int btrfs_subvol_get_info_fd(int fd, uint64_t subvol_id, BtrfsSubvolInfo *ret) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
} else {
|
} else {
|
||||||
r = btrfs_is_filesystem(fd);
|
r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (!r)
|
if (!r)
|
||||||
@ -575,7 +564,7 @@ int btrfs_qgroup_get_quota_fd(int fd, uint64_t qgroupid, BtrfsQuotaInfo *ret) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
} else {
|
} else {
|
||||||
r = btrfs_is_filesystem(fd);
|
r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (!r)
|
if (!r)
|
||||||
@ -762,21 +751,6 @@ int btrfs_subvol_get_subtree_quota(const char *path, uint64_t subvol_id, BtrfsQu
|
|||||||
return btrfs_subvol_get_subtree_quota_fd(fd, subvol_id, ret);
|
return btrfs_subvol_get_subtree_quota_fd(fd, subvol_id, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_defrag_fd(int fd) {
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(fd >= 0);
|
|
||||||
|
|
||||||
r = fd_verify_regular(fd);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (ioctl(fd, BTRFS_IOC_DEFRAG, NULL) < 0)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int btrfs_defrag(const char *p) {
|
int btrfs_defrag(const char *p) {
|
||||||
_cleanup_close_ int fd = -1;
|
_cleanup_close_ int fd = -1;
|
||||||
|
|
||||||
@ -795,7 +769,7 @@ int btrfs_quota_enable_fd(int fd, bool b) {
|
|||||||
|
|
||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
|
|
||||||
r = btrfs_is_filesystem(fd);
|
r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (!r)
|
if (!r)
|
||||||
@ -832,7 +806,7 @@ int btrfs_qgroup_set_limit_fd(int fd, uint64_t qgroupid, uint64_t referenced_max
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
} else {
|
} else {
|
||||||
r = btrfs_is_filesystem(fd);
|
r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (!r)
|
if (!r)
|
||||||
@ -924,7 +898,7 @@ static int qgroup_create_or_destroy(int fd, bool b, uint64_t qgroupid) {
|
|||||||
};
|
};
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = btrfs_is_filesystem(fd);
|
r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
@ -1042,7 +1016,7 @@ static int qgroup_assign_or_unassign(int fd, bool b, uint64_t child, uint64_t pa
|
|||||||
};
|
};
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = btrfs_is_filesystem(fd);
|
r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
@ -1269,7 +1243,7 @@ int btrfs_qgroup_copy_limits(int fd, uint64_t old_qgroupid, uint64_t new_qgroupi
|
|||||||
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = btrfs_is_filesystem(fd);
|
r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (!r)
|
if (!r)
|
||||||
@ -1738,7 +1712,7 @@ int btrfs_qgroup_find_parents(int fd, uint64_t qgroupid, uint64_t **ret) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
} else {
|
} else {
|
||||||
r = btrfs_is_filesystem(fd);
|
r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (!r)
|
if (!r)
|
||||||
@ -1979,7 +1953,7 @@ int btrfs_subvol_get_parent(int fd, uint64_t subvol_id, uint64_t *ret) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
} else {
|
} else {
|
||||||
r = btrfs_is_filesystem(fd);
|
r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (!r)
|
if (!r)
|
||||||
@ -42,8 +42,6 @@ typedef enum BtrfsRemoveFlags {
|
|||||||
BTRFS_REMOVE_QUOTA = 1 << 1,
|
BTRFS_REMOVE_QUOTA = 1 << 1,
|
||||||
} BtrfsRemoveFlags;
|
} BtrfsRemoveFlags;
|
||||||
|
|
||||||
int btrfs_is_filesystem(int fd);
|
|
||||||
|
|
||||||
int btrfs_is_subvol_fd(int fd);
|
int btrfs_is_subvol_fd(int fd);
|
||||||
int btrfs_is_subvol(const char *path);
|
int btrfs_is_subvol(const char *path);
|
||||||
|
|
||||||
@ -53,7 +51,6 @@ int btrfs_clone_range(int infd, uint64_t in_offset, int ofd, uint64_t out_offset
|
|||||||
int btrfs_get_block_device_fd(int fd, dev_t *dev);
|
int btrfs_get_block_device_fd(int fd, dev_t *dev);
|
||||||
int btrfs_get_block_device(const char *path, dev_t *dev);
|
int btrfs_get_block_device(const char *path, dev_t *dev);
|
||||||
|
|
||||||
int btrfs_defrag_fd(int fd);
|
|
||||||
int btrfs_defrag(const char *p);
|
int btrfs_defrag(const char *p);
|
||||||
|
|
||||||
int btrfs_quota_enable_fd(int fd, bool b);
|
int btrfs_quota_enable_fd(int fd, bool b);
|
||||||
@ -17,6 +17,7 @@
|
|||||||
#include "apparmor-util.h"
|
#include "apparmor-util.h"
|
||||||
#include "architecture.h"
|
#include "architecture.h"
|
||||||
#include "audit-util.h"
|
#include "audit-util.h"
|
||||||
|
#include "blockdev-util.h"
|
||||||
#include "cap-list.h"
|
#include "cap-list.h"
|
||||||
#include "cgroup-util.h"
|
#include "cgroup-util.h"
|
||||||
#include "condition.h"
|
#include "condition.h"
|
||||||
|
|||||||
@ -51,20 +51,10 @@ crypt_token_info (*sym_crypt_token_status)(struct crypt_device *cd, int token, c
|
|||||||
int (*sym_crypt_volume_key_get)(struct crypt_device *cd, int keyslot, char *volume_key, size_t *volume_key_size, const char *passphrase, size_t passphrase_size);
|
int (*sym_crypt_volume_key_get)(struct crypt_device *cd, int keyslot, char *volume_key, size_t *volume_key_size, const char *passphrase, size_t passphrase_size);
|
||||||
|
|
||||||
int dlopen_cryptsetup(void) {
|
int dlopen_cryptsetup(void) {
|
||||||
_cleanup_(dlclosep) void *dl = NULL;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (cryptsetup_dl)
|
r = dlopen_many_sym_or_warn(
|
||||||
return 0; /* Already loaded */
|
&cryptsetup_dl, "libcryptsetup.so.12", LOG_DEBUG,
|
||||||
|
|
||||||
dl = dlopen("libcryptsetup.so.12", RTLD_LAZY);
|
|
||||||
if (!dl)
|
|
||||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
|
||||||
"libcryptsetup support is not installed: %s", dlerror());
|
|
||||||
|
|
||||||
r = dlsym_many_and_warn(
|
|
||||||
dl,
|
|
||||||
LOG_DEBUG,
|
|
||||||
DLSYM_ARG(crypt_activate_by_passphrase),
|
DLSYM_ARG(crypt_activate_by_passphrase),
|
||||||
#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
|
#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
|
||||||
DLSYM_ARG(crypt_activate_by_signed_key),
|
DLSYM_ARG(crypt_activate_by_signed_key),
|
||||||
@ -104,15 +94,10 @@ int dlopen_cryptsetup(void) {
|
|||||||
DLSYM_ARG(crypt_token_max),
|
DLSYM_ARG(crypt_token_max),
|
||||||
#endif
|
#endif
|
||||||
DLSYM_ARG(crypt_token_status),
|
DLSYM_ARG(crypt_token_status),
|
||||||
DLSYM_ARG(crypt_volume_key_get),
|
DLSYM_ARG(crypt_volume_key_get));
|
||||||
NULL);
|
if (r <= 0)
|
||||||
if (r < 0)
|
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
/* Note that we never release the reference here, because there's no real reason to, after all this
|
|
||||||
* was traditionally a regular shared library dependency which lives forever too. */
|
|
||||||
cryptsetup_dl = TAKE_PTR(dl);
|
|
||||||
|
|
||||||
/* Redirect the default logging calls of libcryptsetup to our own logging infra. (Note that
|
/* Redirect the default logging calls of libcryptsetup to our own logging infra. (Note that
|
||||||
* libcryptsetup also maintains per-"struct crypt_device" log functions, which we'll also set
|
* libcryptsetup also maintains per-"struct crypt_device" log functions, which we'll also set
|
||||||
* whenever allocating a "struct crypt_device" context. Why set both? To be defensive: maybe some
|
* whenever allocating a "struct crypt_device" context. Why set both? To be defensive: maybe some
|
||||||
|
|||||||
350
src/shared/data-fd-util.c
Normal file
350
src/shared/data-fd-util.c
Normal file
@ -0,0 +1,350 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "alloc-util.h"
|
||||||
|
#include "copy.h"
|
||||||
|
#include "data-fd-util.h"
|
||||||
|
#include "fd-util.h"
|
||||||
|
#include "fs-util.h"
|
||||||
|
#include "io-util.h"
|
||||||
|
#include "memfd-util.h"
|
||||||
|
#include "tmpfile-util.h"
|
||||||
|
|
||||||
|
/* When the data is smaller or equal to 64K, try to place the copy in a memfd/pipe */
|
||||||
|
#define DATA_FD_MEMORY_LIMIT (64U*1024U)
|
||||||
|
|
||||||
|
/* If memfd/pipe didn't work out, then let's use a file in /tmp up to a size of 1M. If it's large than that use /var/tmp instead. */
|
||||||
|
#define DATA_FD_TMP_LIMIT (1024U*1024U)
|
||||||
|
|
||||||
|
int acquire_data_fd(const void *data, size_t size, unsigned flags) {
|
||||||
|
_cleanup_close_pair_ int pipefds[2] = { -1, -1 };
|
||||||
|
char pattern[] = "/dev/shm/data-fd-XXXXXX";
|
||||||
|
_cleanup_close_ int fd = -1;
|
||||||
|
int isz = 0, r;
|
||||||
|
ssize_t n;
|
||||||
|
off_t f;
|
||||||
|
|
||||||
|
assert(data || size == 0);
|
||||||
|
|
||||||
|
/* Acquire a read-only file descriptor that when read from returns the specified data. This is much more
|
||||||
|
* complex than I wish it was. But here's why:
|
||||||
|
*
|
||||||
|
* a) First we try to use memfds. They are the best option, as we can seal them nicely to make them
|
||||||
|
* read-only. Unfortunately they require kernel 3.17, and – at the time of writing – we still support 3.14.
|
||||||
|
*
|
||||||
|
* b) Then, we try classic pipes. They are the second best options, as we can close the writing side, retaining
|
||||||
|
* a nicely read-only fd in the reading side. However, they are by default quite small, and unprivileged
|
||||||
|
* clients can only bump their size to a system-wide limit, which might be quite low.
|
||||||
|
*
|
||||||
|
* c) Then, we try an O_TMPFILE file in /dev/shm (that dir is the only suitable one known to exist from
|
||||||
|
* earliest boot on). To make it read-only we open the fd a second time with O_RDONLY via
|
||||||
|
* /proc/self/<fd>. Unfortunately O_TMPFILE is not available on older kernels on tmpfs.
|
||||||
|
*
|
||||||
|
* d) Finally, we try creating a regular file in /dev/shm, which we then delete.
|
||||||
|
*
|
||||||
|
* It sucks a bit that depending on the situation we return very different objects here, but that's Linux I
|
||||||
|
* figure. */
|
||||||
|
|
||||||
|
if (size == 0 && ((flags & ACQUIRE_NO_DEV_NULL) == 0)) {
|
||||||
|
/* As a special case, return /dev/null if we have been called for an empty data block */
|
||||||
|
r = open("/dev/null", O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||||
|
if (r < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & ACQUIRE_NO_MEMFD) == 0) {
|
||||||
|
fd = memfd_new("data-fd");
|
||||||
|
if (fd < 0)
|
||||||
|
goto try_pipe;
|
||||||
|
|
||||||
|
n = write(fd, data, size);
|
||||||
|
if (n < 0)
|
||||||
|
return -errno;
|
||||||
|
if ((size_t) n != size)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
f = lseek(fd, 0, SEEK_SET);
|
||||||
|
if (f != 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
r = memfd_set_sealed(fd);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return TAKE_FD(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
try_pipe:
|
||||||
|
if ((flags & ACQUIRE_NO_PIPE) == 0) {
|
||||||
|
if (pipe2(pipefds, O_CLOEXEC|O_NONBLOCK) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
|
||||||
|
if (isz < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
if ((size_t) isz < size) {
|
||||||
|
isz = (int) size;
|
||||||
|
if (isz < 0 || (size_t) isz != size)
|
||||||
|
return -E2BIG;
|
||||||
|
|
||||||
|
/* Try to bump the pipe size */
|
||||||
|
(void) fcntl(pipefds[1], F_SETPIPE_SZ, isz);
|
||||||
|
|
||||||
|
/* See if that worked */
|
||||||
|
isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
|
||||||
|
if (isz < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
if ((size_t) isz < size)
|
||||||
|
goto try_dev_shm;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = write(pipefds[1], data, size);
|
||||||
|
if (n < 0)
|
||||||
|
return -errno;
|
||||||
|
if ((size_t) n != size)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
(void) fd_nonblock(pipefds[0], false);
|
||||||
|
|
||||||
|
return TAKE_FD(pipefds[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
try_dev_shm:
|
||||||
|
if ((flags & ACQUIRE_NO_TMPFILE) == 0) {
|
||||||
|
fd = open("/dev/shm", O_RDWR|O_TMPFILE|O_CLOEXEC, 0500);
|
||||||
|
if (fd < 0)
|
||||||
|
goto try_dev_shm_without_o_tmpfile;
|
||||||
|
|
||||||
|
n = write(fd, data, size);
|
||||||
|
if (n < 0)
|
||||||
|
return -errno;
|
||||||
|
if ((size_t) n != size)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
/* Let's reopen the thing, in order to get an O_RDONLY fd for the original O_RDWR one */
|
||||||
|
return fd_reopen(fd, O_RDONLY|O_CLOEXEC);
|
||||||
|
}
|
||||||
|
|
||||||
|
try_dev_shm_without_o_tmpfile:
|
||||||
|
if ((flags & ACQUIRE_NO_REGULAR) == 0) {
|
||||||
|
fd = mkostemp_safe(pattern);
|
||||||
|
if (fd < 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
n = write(fd, data, size);
|
||||||
|
if (n < 0) {
|
||||||
|
r = -errno;
|
||||||
|
goto unlink_and_return;
|
||||||
|
}
|
||||||
|
if ((size_t) n != size) {
|
||||||
|
r = -EIO;
|
||||||
|
goto unlink_and_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let's reopen the thing, in order to get an O_RDONLY fd for the original O_RDWR one */
|
||||||
|
r = open(pattern, O_RDONLY|O_CLOEXEC);
|
||||||
|
if (r < 0)
|
||||||
|
r = -errno;
|
||||||
|
|
||||||
|
unlink_and_return:
|
||||||
|
(void) unlink(pattern);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
int copy_data_fd(int fd) {
|
||||||
|
_cleanup_close_ int copy_fd = -1, tmp_fd = -1;
|
||||||
|
_cleanup_free_ void *remains = NULL;
|
||||||
|
size_t remains_size = 0;
|
||||||
|
const char *td;
|
||||||
|
struct stat st;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* Creates a 'data' fd from the specified source fd, containing all the same data in a read-only fashion, but
|
||||||
|
* independent of it (i.e. the source fd can be closed and unmounted after this call succeeded). Tries to be
|
||||||
|
* somewhat smart about where to place the data. In the best case uses a memfd(). If memfd() are not supported
|
||||||
|
* uses a pipe instead. For larger data will use an unlinked file in /tmp, and for even larger data one in
|
||||||
|
* /var/tmp. */
|
||||||
|
|
||||||
|
if (fstat(fd, &st) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
/* For now, let's only accept regular files, sockets, pipes and char devices */
|
||||||
|
if (S_ISDIR(st.st_mode))
|
||||||
|
return -EISDIR;
|
||||||
|
if (S_ISLNK(st.st_mode))
|
||||||
|
return -ELOOP;
|
||||||
|
if (!S_ISREG(st.st_mode) && !S_ISSOCK(st.st_mode) && !S_ISFIFO(st.st_mode) && !S_ISCHR(st.st_mode))
|
||||||
|
return -EBADFD;
|
||||||
|
|
||||||
|
/* If we have reason to believe the data is bounded in size, then let's use memfds or pipes as backing fd. Note
|
||||||
|
* that we use the reported regular file size only as a hint, given that there are plenty special files in
|
||||||
|
* /proc and /sys which report a zero file size but can be read from. */
|
||||||
|
|
||||||
|
if (!S_ISREG(st.st_mode) || st.st_size < DATA_FD_MEMORY_LIMIT) {
|
||||||
|
|
||||||
|
/* Try a memfd first */
|
||||||
|
copy_fd = memfd_new("data-fd");
|
||||||
|
if (copy_fd >= 0) {
|
||||||
|
off_t f;
|
||||||
|
|
||||||
|
r = copy_bytes(fd, copy_fd, DATA_FD_MEMORY_LIMIT, 0);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
f = lseek(copy_fd, 0, SEEK_SET);
|
||||||
|
if (f != 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
if (r == 0) {
|
||||||
|
/* Did it fit into the limit? If so, we are done. */
|
||||||
|
r = memfd_set_sealed(copy_fd);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return TAKE_FD(copy_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hmm, pity, this didn't fit. Let's fall back to /tmp then, see below */
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_cleanup_(close_pairp) int pipefds[2] = { -1, -1 };
|
||||||
|
int isz;
|
||||||
|
|
||||||
|
/* If memfds aren't available, use a pipe. Set O_NONBLOCK so that we will get EAGAIN rather
|
||||||
|
* then block indefinitely when we hit the pipe size limit */
|
||||||
|
|
||||||
|
if (pipe2(pipefds, O_CLOEXEC|O_NONBLOCK) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
|
||||||
|
if (isz < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
/* Try to enlarge the pipe size if necessary */
|
||||||
|
if ((size_t) isz < DATA_FD_MEMORY_LIMIT) {
|
||||||
|
|
||||||
|
(void) fcntl(pipefds[1], F_SETPIPE_SZ, DATA_FD_MEMORY_LIMIT);
|
||||||
|
|
||||||
|
isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
|
||||||
|
if (isz < 0)
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((size_t) isz >= DATA_FD_MEMORY_LIMIT) {
|
||||||
|
|
||||||
|
r = copy_bytes_full(fd, pipefds[1], DATA_FD_MEMORY_LIMIT, 0, &remains, &remains_size, NULL, NULL);
|
||||||
|
if (r < 0 && r != -EAGAIN)
|
||||||
|
return r; /* If we get EAGAIN it could be because of the source or because of
|
||||||
|
* the destination fd, we can't know, as sendfile() and friends won't
|
||||||
|
* tell us. Hence, treat this as reason to fall back, just to be
|
||||||
|
* sure. */
|
||||||
|
if (r == 0) {
|
||||||
|
/* Everything fit in, yay! */
|
||||||
|
(void) fd_nonblock(pipefds[0], false);
|
||||||
|
|
||||||
|
return TAKE_FD(pipefds[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Things didn't fit in. But we read data into the pipe, let's remember that, so that
|
||||||
|
* when writing the new file we incorporate this first. */
|
||||||
|
copy_fd = TAKE_FD(pipefds[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have reason to believe this will fit fine in /tmp, then use that as first fallback. */
|
||||||
|
if ((!S_ISREG(st.st_mode) || st.st_size < DATA_FD_TMP_LIMIT) &&
|
||||||
|
(DATA_FD_MEMORY_LIMIT + remains_size) < DATA_FD_TMP_LIMIT) {
|
||||||
|
off_t f;
|
||||||
|
|
||||||
|
tmp_fd = open_tmpfile_unlinkable(NULL /* NULL as directory means /tmp */, O_RDWR|O_CLOEXEC);
|
||||||
|
if (tmp_fd < 0)
|
||||||
|
return tmp_fd;
|
||||||
|
|
||||||
|
if (copy_fd >= 0) {
|
||||||
|
/* If we tried a memfd/pipe first and it ended up being too large, then copy this into the
|
||||||
|
* temporary file first. */
|
||||||
|
|
||||||
|
r = copy_bytes(copy_fd, tmp_fd, UINT64_MAX, 0);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
assert(r == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remains_size > 0) {
|
||||||
|
/* If there were remaining bytes (i.e. read into memory, but not written out yet) from the
|
||||||
|
* failed copy operation, let's flush them out next. */
|
||||||
|
|
||||||
|
r = loop_write(tmp_fd, remains, remains_size, false);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = copy_bytes(fd, tmp_fd, DATA_FD_TMP_LIMIT - DATA_FD_MEMORY_LIMIT - remains_size, COPY_REFLINK);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (r == 0)
|
||||||
|
goto finish; /* Yay, it fit in */
|
||||||
|
|
||||||
|
/* It didn't fit in. Let's not forget to use what we already used */
|
||||||
|
f = lseek(tmp_fd, 0, SEEK_SET);
|
||||||
|
if (f != 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
CLOSE_AND_REPLACE(copy_fd, tmp_fd);
|
||||||
|
|
||||||
|
remains = mfree(remains);
|
||||||
|
remains_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* As last fallback use /var/tmp */
|
||||||
|
r = var_tmp_dir(&td);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
tmp_fd = open_tmpfile_unlinkable(td, O_RDWR|O_CLOEXEC);
|
||||||
|
if (tmp_fd < 0)
|
||||||
|
return tmp_fd;
|
||||||
|
|
||||||
|
if (copy_fd >= 0) {
|
||||||
|
/* If we tried a memfd/pipe first, or a file in /tmp, and it ended up being too large, than copy this
|
||||||
|
* into the temporary file first. */
|
||||||
|
r = copy_bytes(copy_fd, tmp_fd, UINT64_MAX, COPY_REFLINK);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
assert(r == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remains_size > 0) {
|
||||||
|
/* Then, copy in any read but not yet written bytes. */
|
||||||
|
r = loop_write(tmp_fd, remains, remains_size, false);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy in the rest */
|
||||||
|
r = copy_bytes(fd, tmp_fd, UINT64_MAX, COPY_REFLINK);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
assert(r == 0);
|
||||||
|
|
||||||
|
finish:
|
||||||
|
/* Now convert the O_RDWR file descriptor into an O_RDONLY one (and as side effect seek to the beginning of the
|
||||||
|
* file again */
|
||||||
|
|
||||||
|
return fd_reopen(tmp_fd, O_RDONLY|O_CLOEXEC);
|
||||||
|
}
|
||||||
7
src/shared/data-fd-util.h
Normal file
7
src/shared/data-fd-util.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
int acquire_data_fd(const void *data, size_t size, unsigned flags);
|
||||||
|
int copy_data_fd(int fd);
|
||||||
@ -4,6 +4,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/loop.h>
|
#include <linux/loop.h>
|
||||||
|
#include <linux/magic.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
@ -34,6 +35,7 @@
|
|||||||
#include "os-util.h"
|
#include "os-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "rm-rf.h"
|
#include "rm-rf.h"
|
||||||
|
#include "stat-util.h"
|
||||||
#include "string-table.h"
|
#include "string-table.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
@ -262,7 +264,7 @@ static int image_make(
|
|||||||
|
|
||||||
if (btrfs_might_be_subvol(st)) {
|
if (btrfs_might_be_subvol(st)) {
|
||||||
|
|
||||||
r = btrfs_is_filesystem(fd);
|
r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r) {
|
if (r) {
|
||||||
|
|||||||
64
src/shared/dlfcn-util.c
Normal file
64
src/shared/dlfcn-util.c
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
#include "dlfcn-util.h"
|
||||||
|
|
||||||
|
static int dlsym_many_or_warnv(void *dl, int log_level, va_list ap) {
|
||||||
|
void (**fn)(void);
|
||||||
|
|
||||||
|
/* Tries to resolve a bunch of function symbols, and logs an error about if it cannot resolve one of
|
||||||
|
* them. Note that this function possibly modifies the supplied function pointers if the whole
|
||||||
|
* operation fails. */
|
||||||
|
|
||||||
|
while ((fn = va_arg(ap, typeof(fn)))) {
|
||||||
|
void (*tfn)(void);
|
||||||
|
const char *symbol;
|
||||||
|
|
||||||
|
symbol = va_arg(ap, typeof(symbol));
|
||||||
|
|
||||||
|
tfn = (typeof(tfn)) dlsym(dl, symbol);
|
||||||
|
if (!tfn)
|
||||||
|
return log_full_errno(log_level,
|
||||||
|
SYNTHETIC_ERRNO(ELIBBAD),
|
||||||
|
"Can't find symbol %s: %s", symbol, dlerror());
|
||||||
|
*fn = tfn;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dlsym_many_or_warn_sentinel(void *dl, int log_level, ...) {
|
||||||
|
va_list ap;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
va_start(ap, log_level);
|
||||||
|
r = dlsym_many_or_warnv(dl, log_level, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dlopen_many_sym_or_warn_sentinel(void **dlp, const char *filename, int log_level, ...) {
|
||||||
|
_cleanup_(dlclosep) void *dl = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (*dlp)
|
||||||
|
return 0; /* Already loaded */
|
||||||
|
|
||||||
|
dl = dlopen(filename, RTLD_LAZY);
|
||||||
|
if (!dl)
|
||||||
|
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||||
|
"%s is not installed: %s", filename, dlerror());
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, log_level);
|
||||||
|
r = dlsym_many_or_warnv(dl, log_level, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
/* Note that we never release the reference here, because there's no real reason to. After all this
|
||||||
|
* was traditionally a regular shared library dependency which lives forever too. */
|
||||||
|
*dlp = TAKE_PTR(dl);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
22
src/shared/dlfcn-util.h
Normal file
22
src/shared/dlfcn-util.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
#include "macro.h"
|
||||||
|
|
||||||
|
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(void*, dlclose, NULL);
|
||||||
|
|
||||||
|
int dlsym_many_or_warn_sentinel(void *dl, int log_level, ...) _sentinel_;
|
||||||
|
int dlopen_many_sym_or_warn_sentinel(void **dlp, const char *filename, int log_level, ...) _sentinel_;
|
||||||
|
|
||||||
|
#define dlsym_many_or_warn(dl, log_level, ...) \
|
||||||
|
dlsym_many_or_warn_sentinel(dl, log_level, __VA_ARGS__, NULL)
|
||||||
|
#define dlopen_many_sym_or_warn(dlp, filename, log_level, ...) \
|
||||||
|
dlopen_many_sym_or_warn_sentinel(dlp, filename, log_level, __VA_ARGS__, NULL)
|
||||||
|
|
||||||
|
/* Macro useful for putting together variable/symbol name pairs when calling dlsym_many_or_warn(). Assumes
|
||||||
|
* that each library symbol to resolve will be placed in a variable with the "sym_" prefix, i.e. a symbol
|
||||||
|
* "foobar" is loaded into a variable "sym_foobar". */
|
||||||
|
#define DLSYM_ARG(arg) \
|
||||||
|
&sym_##arg, STRINGIFY(arg)
|
||||||
@ -13,6 +13,7 @@
|
|||||||
#include "hwdb-util.h"
|
#include "hwdb-util.h"
|
||||||
#include "label.h"
|
#include "label.h"
|
||||||
#include "mkdir.h"
|
#include "mkdir.h"
|
||||||
|
#include "nulstr-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "sort-util.h"
|
#include "sort-util.h"
|
||||||
#include "strbuf.h"
|
#include "strbuf.h"
|
||||||
@ -586,10 +587,10 @@ int hwdb_update(const char *root, const char *hwdb_bin_dir, bool strict, bool co
|
|||||||
uint16_t file_priority = 1;
|
uint16_t file_priority = 1;
|
||||||
int r = 0, err;
|
int r = 0, err;
|
||||||
|
|
||||||
/* The argument 'compat' controls the format version of database. If false, then hwdb.bin will be created with
|
/* The argument 'compat' controls the format version of database. If false, then hwdb.bin will be
|
||||||
* additional information such that priority, line number, and filename of database source. If true, then hwdb.bin
|
* created with additional information such that priority, line number, and filename of database
|
||||||
* will be created without the information. systemd-hwdb command should set the argument false, and 'udevadm hwdb'
|
* source. If true, then hwdb.bin will be created without the information. systemd-hwdb command
|
||||||
* command should set it true. */
|
* should set the argument false, and 'udevadm hwdb' command should set it true. */
|
||||||
|
|
||||||
trie = new0(struct trie, 1);
|
trie = new0(struct trie, 1);
|
||||||
if (!trie)
|
if (!trie)
|
||||||
@ -666,3 +667,27 @@ int hwdb_query(const char *modalias) {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hwdb_validate(sd_hwdb *hwdb) {
|
||||||
|
bool found = false;
|
||||||
|
const char* p;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (!hwdb)
|
||||||
|
return false;
|
||||||
|
if (!hwdb->f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* if hwdb.bin doesn't exist anywhere, we need to update */
|
||||||
|
NULSTR_FOREACH(p, hwdb_bin_paths)
|
||||||
|
if (stat(p, &st) >= 0) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (timespec_load(&hwdb->st.st_mtim) != timespec_load(&st.st_mtim))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@ -21,32 +21,11 @@ const char *(*sym_idn2_strerror)(int rc) = NULL;
|
|||||||
int (*sym_idn2_to_unicode_8z8z)(const char * input, char ** output, int flags) = NULL;
|
int (*sym_idn2_to_unicode_8z8z)(const char * input, char ** output, int flags) = NULL;
|
||||||
|
|
||||||
int dlopen_idn(void) {
|
int dlopen_idn(void) {
|
||||||
_cleanup_(dlclosep) void *dl = NULL;
|
return dlopen_many_sym_or_warn(
|
||||||
int r;
|
&idn_dl, "libidn2.so.0", LOG_DEBUG,
|
||||||
|
|
||||||
if (idn_dl)
|
|
||||||
return 0; /* Already loaded */
|
|
||||||
|
|
||||||
dl = dlopen("libidn2.so.0", RTLD_LAZY);
|
|
||||||
if (!dl)
|
|
||||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
|
||||||
"libidn2 support is not installed: %s", dlerror());
|
|
||||||
|
|
||||||
r = dlsym_many_and_warn(
|
|
||||||
dl,
|
|
||||||
LOG_DEBUG,
|
|
||||||
DLSYM_ARG(idn2_lookup_u8),
|
DLSYM_ARG(idn2_lookup_u8),
|
||||||
DLSYM_ARG(idn2_strerror),
|
DLSYM_ARG(idn2_strerror),
|
||||||
DLSYM_ARG(idn2_to_unicode_8z8z),
|
DLSYM_ARG(idn2_to_unicode_8z8z));
|
||||||
NULL);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
/* Note that we never release the reference here, because there's no real reason to, after all this
|
|
||||||
* was traditionally a regular shared library dependency which lives forever too. */
|
|
||||||
idn_dl = TAKE_PTR(dl);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -73,14 +52,13 @@ int dlopen_idn(void) {
|
|||||||
"libidn support is not installed: %s", dlerror());
|
"libidn support is not installed: %s", dlerror());
|
||||||
}
|
}
|
||||||
|
|
||||||
r = dlsym_many_and_warn(
|
r = dlsym_many_or_warn(
|
||||||
dl,
|
dl,
|
||||||
LOG_DEBUG,
|
LOG_DEBUG,
|
||||||
DLSYM_ARG(idna_to_ascii_4i),
|
DLSYM_ARG(idna_to_ascii_4i),
|
||||||
DLSYM_ARG(idna_to_unicode_44i),
|
DLSYM_ARG(idna_to_unicode_44i),
|
||||||
DLSYM_ARG(stringprep_ucs4_to_utf8),
|
DLSYM_ARG(stringprep_ucs4_to_utf8),
|
||||||
DLSYM_ARG(stringprep_utf8_to_ucs4),
|
DLSYM_ARG(stringprep_utf8_to_ucs4));
|
||||||
NULL);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -568,8 +568,6 @@ static int remove_marked_symlinks_fd(
|
|||||||
|
|
||||||
FOREACH_DIRENT(de, d, return -errno) {
|
FOREACH_DIRENT(de, d, return -errno) {
|
||||||
|
|
||||||
dirent_ensure_type(d, de);
|
|
||||||
|
|
||||||
if (de->d_type == DT_DIR) {
|
if (de->d_type == DT_DIR) {
|
||||||
_cleanup_free_ char *p = NULL;
|
_cleanup_free_ char *p = NULL;
|
||||||
int nfd, q;
|
int nfd, q;
|
||||||
@ -738,8 +736,6 @@ static int find_symlinks_in_directory(
|
|||||||
bool found_path = false, found_dest, b = false;
|
bool found_path = false, found_dest, b = false;
|
||||||
int q;
|
int q;
|
||||||
|
|
||||||
dirent_ensure_type(dir, de);
|
|
||||||
|
|
||||||
if (de->d_type != DT_LNK)
|
if (de->d_type != DT_LNK)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -836,8 +832,6 @@ static int find_symlinks(
|
|||||||
_cleanup_free_ const char *path = NULL;
|
_cleanup_free_ const char *path = NULL;
|
||||||
_cleanup_closedir_ DIR *d = NULL;
|
_cleanup_closedir_ DIR *d = NULL;
|
||||||
|
|
||||||
dirent_ensure_type(config_dir, de);
|
|
||||||
|
|
||||||
if (de->d_type != DT_DIR)
|
if (de->d_type != DT_DIR)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -3379,8 +3373,6 @@ int unit_file_preset_all(
|
|||||||
if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
|
if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
dirent_ensure_type(d, de);
|
|
||||||
|
|
||||||
if (!IN_SET(de->d_type, DT_LNK, DT_REG))
|
if (!IN_SET(de->d_type, DT_LNK, DT_REG))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -3457,8 +3449,6 @@ int unit_file_get_list(
|
|||||||
if (hashmap_get(h, de->d_name))
|
if (hashmap_get(h, de->d_name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
dirent_ensure_type(d, de);
|
|
||||||
|
|
||||||
if (!IN_SET(de->d_type, DT_LNK, DT_REG))
|
if (!IN_SET(de->d_type, DT_LNK, DT_REG))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@ -61,20 +61,8 @@ int (*sym_fido_dev_open)(fido_dev_t *, const char *) = NULL;
|
|||||||
const char* (*sym_fido_strerr)(int) = NULL;
|
const char* (*sym_fido_strerr)(int) = NULL;
|
||||||
|
|
||||||
int dlopen_libfido2(void) {
|
int dlopen_libfido2(void) {
|
||||||
_cleanup_(dlclosep) void *dl = NULL;
|
return dlopen_many_sym_or_warn(
|
||||||
int r;
|
&libfido2_dl, "libfido2.so.1", LOG_DEBUG,
|
||||||
|
|
||||||
if (libfido2_dl)
|
|
||||||
return 0; /* Already loaded */
|
|
||||||
|
|
||||||
dl = dlopen("libfido2.so.1", RTLD_LAZY);
|
|
||||||
if (!dl)
|
|
||||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
|
||||||
"libfido2 support is not installed: %s", dlerror());
|
|
||||||
|
|
||||||
r = dlsym_many_and_warn(
|
|
||||||
dl,
|
|
||||||
LOG_DEBUG,
|
|
||||||
DLSYM_ARG(fido_assert_allow_cred),
|
DLSYM_ARG(fido_assert_allow_cred),
|
||||||
DLSYM_ARG(fido_assert_free),
|
DLSYM_ARG(fido_assert_free),
|
||||||
DLSYM_ARG(fido_assert_hmac_secret_len),
|
DLSYM_ARG(fido_assert_hmac_secret_len),
|
||||||
@ -118,15 +106,7 @@ int dlopen_libfido2(void) {
|
|||||||
DLSYM_ARG(fido_dev_make_cred),
|
DLSYM_ARG(fido_dev_make_cred),
|
||||||
DLSYM_ARG(fido_dev_new),
|
DLSYM_ARG(fido_dev_new),
|
||||||
DLSYM_ARG(fido_dev_open),
|
DLSYM_ARG(fido_dev_open),
|
||||||
DLSYM_ARG(fido_strerr),
|
DLSYM_ARG(fido_strerr));
|
||||||
NULL);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
/* Note that we never release the reference here, because there's no real reason to, after all this
|
|
||||||
* was traditionally a regular shared library dependency which lives forever too. */
|
|
||||||
libfido2_dl = TAKE_PTR(dl);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int verify_features(
|
static int verify_features(
|
||||||
|
|||||||
@ -17,6 +17,8 @@ shared_sources = files('''
|
|||||||
bitmap.c
|
bitmap.c
|
||||||
bitmap.h
|
bitmap.h
|
||||||
blkid-util.h
|
blkid-util.h
|
||||||
|
blockdev-util.c
|
||||||
|
blockdev-util.h
|
||||||
bond-util.c
|
bond-util.c
|
||||||
bond-util.h
|
bond-util.h
|
||||||
boot-timestamps.c
|
boot-timestamps.c
|
||||||
@ -29,6 +31,8 @@ shared_sources = files('''
|
|||||||
bpf-program.h
|
bpf-program.h
|
||||||
bridge-util.c
|
bridge-util.c
|
||||||
bridge-util.h
|
bridge-util.h
|
||||||
|
btrfs-util.c
|
||||||
|
btrfs-util.h
|
||||||
bus-get-properties.c
|
bus-get-properties.c
|
||||||
bus-get-properties.h
|
bus-get-properties.h
|
||||||
bus-locator.c
|
bus-locator.c
|
||||||
@ -71,6 +75,8 @@ shared_sources = files('''
|
|||||||
condition.h
|
condition.h
|
||||||
conf-parser.c
|
conf-parser.c
|
||||||
conf-parser.h
|
conf-parser.h
|
||||||
|
copy.c
|
||||||
|
copy.h
|
||||||
coredump-util.c
|
coredump-util.c
|
||||||
coredump-util.h
|
coredump-util.h
|
||||||
cpu-set-util.c
|
cpu-set-util.c
|
||||||
@ -78,6 +84,8 @@ shared_sources = files('''
|
|||||||
cryptsetup-util.c
|
cryptsetup-util.c
|
||||||
cryptsetup-util.h
|
cryptsetup-util.h
|
||||||
daemon-util.h
|
daemon-util.h
|
||||||
|
data-fd-util.c
|
||||||
|
data-fd-util.h
|
||||||
dev-setup.c
|
dev-setup.c
|
||||||
dev-setup.h
|
dev-setup.h
|
||||||
device-nodes.c
|
device-nodes.c
|
||||||
@ -87,6 +95,8 @@ shared_sources = files('''
|
|||||||
discover-image.h
|
discover-image.h
|
||||||
dissect-image.c
|
dissect-image.c
|
||||||
dissect-image.h
|
dissect-image.h
|
||||||
|
dlfcn-util.c
|
||||||
|
dlfcn-util.h
|
||||||
dm-util.c
|
dm-util.c
|
||||||
dm-util.h
|
dm-util.h
|
||||||
dns-domain.c
|
dns-domain.c
|
||||||
@ -129,6 +139,8 @@ shared_sources = files('''
|
|||||||
group-record.h
|
group-record.h
|
||||||
hostname-setup.c
|
hostname-setup.c
|
||||||
hostname-setup.h
|
hostname-setup.h
|
||||||
|
hwdb-util.c
|
||||||
|
hwdb-util.h
|
||||||
id128-print.c
|
id128-print.c
|
||||||
id128-print.h
|
id128-print.h
|
||||||
idn-util.c
|
idn-util.c
|
||||||
@ -142,10 +154,10 @@ shared_sources = files('''
|
|||||||
install-printf.h
|
install-printf.h
|
||||||
install.c
|
install.c
|
||||||
install.h
|
install.h
|
||||||
ipvlan-util.c
|
|
||||||
ipvlan-util.h
|
|
||||||
ip-protocol-list.c
|
ip-protocol-list.c
|
||||||
ip-protocol-list.h
|
ip-protocol-list.h
|
||||||
|
ipvlan-util.c
|
||||||
|
ipvlan-util.h
|
||||||
journal-importer.c
|
journal-importer.c
|
||||||
journal-importer.h
|
journal-importer.h
|
||||||
journal-util.c
|
journal-util.c
|
||||||
@ -157,6 +169,8 @@ shared_sources = files('''
|
|||||||
kbd-util.h
|
kbd-util.h
|
||||||
killall.c
|
killall.c
|
||||||
killall.h
|
killall.h
|
||||||
|
label.c
|
||||||
|
label.h
|
||||||
libcrypt-util.c
|
libcrypt-util.c
|
||||||
libcrypt-util.h
|
libcrypt-util.h
|
||||||
libfido2-util.c
|
libfido2-util.c
|
||||||
@ -186,6 +200,7 @@ shared_sources = files('''
|
|||||||
macvlan-util.c
|
macvlan-util.c
|
||||||
macvlan-util.h
|
macvlan-util.h
|
||||||
main-func.h
|
main-func.h
|
||||||
|
mkdir-label.c
|
||||||
mkfs-util.c
|
mkfs-util.c
|
||||||
mkfs-util.h
|
mkfs-util.h
|
||||||
module-util.h
|
module-util.h
|
||||||
@ -223,21 +238,30 @@ shared_sources = files('''
|
|||||||
pwquality-util.h
|
pwquality-util.h
|
||||||
qrcode-util.c
|
qrcode-util.c
|
||||||
qrcode-util.h
|
qrcode-util.h
|
||||||
|
quota-util.c
|
||||||
|
quota-util.h
|
||||||
reboot-util.c
|
reboot-util.c
|
||||||
reboot-util.h
|
reboot-util.h
|
||||||
resize-fs.c
|
resize-fs.c
|
||||||
resize-fs.h
|
resize-fs.h
|
||||||
resolve-util.c
|
resolve-util.c
|
||||||
resolve-util.h
|
resolve-util.h
|
||||||
|
rm-rf.c
|
||||||
|
rm-rf.h
|
||||||
seccomp-util.h
|
seccomp-util.h
|
||||||
securebits-util.c
|
securebits-util.c
|
||||||
securebits-util.h
|
securebits-util.h
|
||||||
|
selinux-util.c
|
||||||
|
selinux-util.h
|
||||||
serialize.c
|
serialize.c
|
||||||
serialize.h
|
serialize.h
|
||||||
service-util.c
|
service-util.c
|
||||||
service-util.h
|
service-util.h
|
||||||
sleep-config.c
|
sleep-config.c
|
||||||
sleep-config.h
|
sleep-config.h
|
||||||
|
smack-util.c
|
||||||
|
smack-util.h
|
||||||
|
socket-label.c
|
||||||
socket-netlink.c
|
socket-netlink.c
|
||||||
socket-netlink.h
|
socket-netlink.h
|
||||||
spawn-ask-password-agent.c
|
spawn-ask-password-agent.c
|
||||||
@ -264,10 +288,10 @@ shared_sources = files('''
|
|||||||
user-record-show.h
|
user-record-show.h
|
||||||
user-record.c
|
user-record.c
|
||||||
user-record.h
|
user-record.h
|
||||||
userdb.c
|
|
||||||
userdb.h
|
|
||||||
userdb-dropin.c
|
userdb-dropin.c
|
||||||
userdb-dropin.h
|
userdb-dropin.h
|
||||||
|
userdb.c
|
||||||
|
userdb.h
|
||||||
utmp-wtmp.h
|
utmp-wtmp.h
|
||||||
varlink.c
|
varlink.c
|
||||||
varlink.h
|
varlink.h
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "fs-util.h"
|
#include "fs-util.h"
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
|
#include "label.h"
|
||||||
#include "libmount-util.h"
|
#include "libmount-util.h"
|
||||||
#include "missing_mount.h"
|
#include "missing_mount.h"
|
||||||
#include "missing_syscall.h"
|
#include "missing_syscall.h"
|
||||||
@ -1071,3 +1072,25 @@ int remount_idmap(
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int make_mount_point_inode_from_stat(const struct stat *st, const char *dest, mode_t mode) {
|
||||||
|
assert(st);
|
||||||
|
assert(dest);
|
||||||
|
|
||||||
|
if (S_ISDIR(st->st_mode))
|
||||||
|
return mkdir_label(dest, mode);
|
||||||
|
else
|
||||||
|
return mknod(dest, S_IFREG|(mode & ~0111), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int make_mount_point_inode_from_path(const char *source, const char *dest, mode_t mode) {
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
assert(source);
|
||||||
|
assert(dest);
|
||||||
|
|
||||||
|
if (stat(source, &st) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return make_mount_point_inode_from_stat(&st, dest, mode);
|
||||||
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <mntent.h>
|
#include <mntent.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
@ -108,3 +109,7 @@ int mount_image_in_namespace(pid_t target, const char *propagate_path, const cha
|
|||||||
int make_mount_point(const char *path);
|
int make_mount_point(const char *path);
|
||||||
|
|
||||||
int remount_idmap(const char *p, uid_t uid_shift, uid_t uid_range);
|
int remount_idmap(const char *p, uid_t uid_shift, uid_t uid_range);
|
||||||
|
|
||||||
|
/* Creates a mount point (not parents) based on the source path or stat - ie, a file or a directory */
|
||||||
|
int make_mount_point_inode_from_stat(const struct stat *st, const char *dest, mode_t mode);
|
||||||
|
int make_mount_point_inode_from_path(const char *source, const char *dest, mode_t mode);
|
||||||
|
|||||||
@ -139,8 +139,6 @@ static int numa_max_node(void) {
|
|||||||
int node;
|
int node;
|
||||||
const char *n;
|
const char *n;
|
||||||
|
|
||||||
(void) dirent_ensure_type(d, de);
|
|
||||||
|
|
||||||
if (de->d_type != DT_DIR)
|
if (de->d_type != DT_DIR)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,8 @@
|
|||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
|
|
||||||
#if HAVE_OPENSSL
|
#if HAVE_OPENSSL
|
||||||
# include <openssl/pem.h>
|
# include <openssl/evp.h>
|
||||||
|
# include <openssl/x509.h>
|
||||||
|
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(X509*, X509_free, NULL);
|
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(X509*, X509_free, NULL);
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(X509_NAME*, X509_NAME_free, NULL);
|
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(X509_NAME*, X509_NAME_free, NULL);
|
||||||
|
|||||||
@ -24,20 +24,8 @@ int (*sym_pwquality_set_int_value)(pwquality_settings_t *pwq, int setting, int v
|
|||||||
const char* (*sym_pwquality_strerror)(char *buf, size_t len, int errcode, void *auxerror);
|
const char* (*sym_pwquality_strerror)(char *buf, size_t len, int errcode, void *auxerror);
|
||||||
|
|
||||||
int dlopen_pwquality(void) {
|
int dlopen_pwquality(void) {
|
||||||
_cleanup_(dlclosep) void *dl = NULL;
|
return dlopen_many_sym_or_warn(
|
||||||
int r;
|
&pwquality_dl, "libpwquality.so.1", LOG_DEBUG,
|
||||||
|
|
||||||
if (pwquality_dl)
|
|
||||||
return 0; /* Already loaded */
|
|
||||||
|
|
||||||
dl = dlopen("libpwquality.so.1", RTLD_LAZY);
|
|
||||||
if (!dl)
|
|
||||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
|
||||||
"libpwquality support is not installed: %s", dlerror());
|
|
||||||
|
|
||||||
r = dlsym_many_and_warn(
|
|
||||||
dl,
|
|
||||||
LOG_DEBUG,
|
|
||||||
DLSYM_ARG(pwquality_check),
|
DLSYM_ARG(pwquality_check),
|
||||||
DLSYM_ARG(pwquality_default_settings),
|
DLSYM_ARG(pwquality_default_settings),
|
||||||
DLSYM_ARG(pwquality_free_settings),
|
DLSYM_ARG(pwquality_free_settings),
|
||||||
@ -45,15 +33,7 @@ int dlopen_pwquality(void) {
|
|||||||
DLSYM_ARG(pwquality_get_str_value),
|
DLSYM_ARG(pwquality_get_str_value),
|
||||||
DLSYM_ARG(pwquality_read_config),
|
DLSYM_ARG(pwquality_read_config),
|
||||||
DLSYM_ARG(pwquality_set_int_value),
|
DLSYM_ARG(pwquality_set_int_value),
|
||||||
DLSYM_ARG(pwquality_strerror),
|
DLSYM_ARG(pwquality_strerror));
|
||||||
NULL);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
/* Note that we never release the reference here, because there's no real reason to, after all this
|
|
||||||
* was traditionally a regular shared library dependency which lives forever too. */
|
|
||||||
pwquality_dl = TAKE_PTR(dl);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pwq_maybe_disable_dictionary(pwquality_settings_t *pwq) {
|
void pwq_maybe_disable_dictionary(pwquality_settings_t *pwq) {
|
||||||
|
|||||||
@ -5,9 +5,9 @@
|
|||||||
#if HAVE_QRENCODE
|
#if HAVE_QRENCODE
|
||||||
#include <qrencode.h>
|
#include <qrencode.h>
|
||||||
|
|
||||||
#include "alloc-util.h"
|
|
||||||
#include "dlfcn-util.h"
|
#include "dlfcn-util.h"
|
||||||
#include "locale-util.h"
|
#include "locale-util.h"
|
||||||
|
#include "log.h"
|
||||||
#include "terminal-util.h"
|
#include "terminal-util.h"
|
||||||
|
|
||||||
#define ANSI_WHITE_ON_BLACK "\033[40;37;1m"
|
#define ANSI_WHITE_ON_BLACK "\033[40;37;1m"
|
||||||
@ -18,30 +18,10 @@ static QRcode* (*sym_QRcode_encodeString)(const char *string, int version, QRecL
|
|||||||
static void (*sym_QRcode_free)(QRcode *qrcode) = NULL;
|
static void (*sym_QRcode_free)(QRcode *qrcode) = NULL;
|
||||||
|
|
||||||
int dlopen_qrencode(void) {
|
int dlopen_qrencode(void) {
|
||||||
_cleanup_(dlclosep) void *dl = NULL;
|
return dlopen_many_sym_or_warn(
|
||||||
int r;
|
&qrcode_dl, "libqrencode.so.4", LOG_DEBUG,
|
||||||
|
|
||||||
if (qrcode_dl)
|
|
||||||
return 0; /* Already loaded */
|
|
||||||
|
|
||||||
dl = dlopen("libqrencode.so.4", RTLD_LAZY);
|
|
||||||
if (!dl)
|
|
||||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
|
||||||
"libqrcode support is not installed: %s", dlerror());
|
|
||||||
|
|
||||||
r = dlsym_many_and_warn(
|
|
||||||
dl,
|
|
||||||
LOG_DEBUG,
|
|
||||||
DLSYM_ARG(QRcode_encodeString),
|
DLSYM_ARG(QRcode_encodeString),
|
||||||
DLSYM_ARG(QRcode_free),
|
DLSYM_ARG(QRcode_free));
|
||||||
NULL);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
/* Note that we never release the reference here, because there's no real reason to, after all this
|
|
||||||
* was traditionally a regular shared library dependency which lives forever too. */
|
|
||||||
qrcode_dl = TAKE_PTR(dl);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_border(FILE *output, unsigned width) {
|
static void print_border(FILE *output, unsigned width) {
|
||||||
|
|||||||
@ -36,9 +36,9 @@ static int mac_selinux_reload(int seqno);
|
|||||||
|
|
||||||
static int cached_use = -1;
|
static int cached_use = -1;
|
||||||
static bool initialized = false;
|
static bool initialized = false;
|
||||||
static int (*enforcing_status_func)(void) = security_getenforce;
|
|
||||||
static int last_policyload = 0;
|
static int last_policyload = 0;
|
||||||
static struct selabel_handle *label_hnd = NULL;
|
static struct selabel_handle *label_hnd = NULL;
|
||||||
|
static bool have_status_page = false;
|
||||||
|
|
||||||
#define log_enforcing(...) \
|
#define log_enforcing(...) \
|
||||||
log_full(mac_selinux_enforcing() ? LOG_ERR : LOG_WARNING, __VA_ARGS__)
|
log_full(mac_selinux_enforcing() ? LOG_ERR : LOG_WARNING, __VA_ARGS__)
|
||||||
@ -70,11 +70,19 @@ bool mac_selinux_use(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool mac_selinux_enforcing(void) {
|
bool mac_selinux_enforcing(void) {
|
||||||
|
int r = 0;
|
||||||
#if HAVE_SELINUX
|
#if HAVE_SELINUX
|
||||||
return enforcing_status_func() != 0;
|
|
||||||
#else
|
/* If the SELinux status page has been successfully opened, retrieve the enforcing
|
||||||
return false;
|
* status over it to avoid system calls in security_getenforce(). */
|
||||||
|
|
||||||
|
if (have_status_page)
|
||||||
|
r = selinux_status_getenforce();
|
||||||
|
else
|
||||||
|
r = security_getenforce();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
return r != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mac_selinux_retest(void) {
|
void mac_selinux_retest(void) {
|
||||||
@ -142,7 +150,6 @@ static int open_label_db(void) {
|
|||||||
int mac_selinux_init(void) {
|
int mac_selinux_init(void) {
|
||||||
#if HAVE_SELINUX
|
#if HAVE_SELINUX
|
||||||
int r;
|
int r;
|
||||||
bool have_status_page = false;
|
|
||||||
|
|
||||||
if (initialized)
|
if (initialized)
|
||||||
return 0;
|
return 0;
|
||||||
@ -170,11 +177,6 @@ int mac_selinux_init(void) {
|
|||||||
* first call without any actual change. */
|
* first call without any actual change. */
|
||||||
last_policyload = selinux_status_policyload();
|
last_policyload = selinux_status_policyload();
|
||||||
|
|
||||||
if (have_status_page)
|
|
||||||
/* Now that the SELinux status page has been successfully opened, retrieve the enforcing
|
|
||||||
* status over it (to avoid system calls in security_getenforce()). */
|
|
||||||
enforcing_status_func = selinux_status_getenforce;
|
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
@ -215,9 +217,8 @@ void mac_selinux_finish(void) {
|
|||||||
label_hnd = NULL;
|
label_hnd = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
enforcing_status_func = security_getenforce;
|
|
||||||
|
|
||||||
selinux_status_close();
|
selinux_status_close();
|
||||||
|
have_status_page = false;
|
||||||
|
|
||||||
initialized = false;
|
initialized = false;
|
||||||
#endif
|
#endif
|
||||||
@ -6,6 +6,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
#include <linux/magic.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
@ -28,6 +29,7 @@
|
|||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "sleep-config.h"
|
#include "sleep-config.h"
|
||||||
|
#include "stat-util.h"
|
||||||
#include "stdio-util.h"
|
#include "stdio-util.h"
|
||||||
#include "string-table.h"
|
#include "string-table.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
@ -232,7 +234,7 @@ static int calculate_swap_file_offset(const SwapEntry *swap, uint64_t *ret_offse
|
|||||||
_cleanup_close_ int fd = -1;
|
_cleanup_close_ int fd = -1;
|
||||||
_cleanup_free_ struct fiemap *fiemap = NULL;
|
_cleanup_free_ struct fiemap *fiemap = NULL;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
int r, btrfs;
|
int r;
|
||||||
|
|
||||||
assert(swap);
|
assert(swap);
|
||||||
assert(swap->device);
|
assert(swap->device);
|
||||||
@ -245,10 +247,10 @@ static int calculate_swap_file_offset(const SwapEntry *swap, uint64_t *ret_offse
|
|||||||
if (fstat(fd, &sb) < 0)
|
if (fstat(fd, &sb) < 0)
|
||||||
return log_debug_errno(errno, "Failed to stat %s: %m", swap->device);
|
return log_debug_errno(errno, "Failed to stat %s: %m", swap->device);
|
||||||
|
|
||||||
btrfs = btrfs_is_filesystem(fd);
|
r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
|
||||||
if (btrfs < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(btrfs, "Error checking %s for Btrfs filesystem: %m", swap->device);
|
return log_debug_errno(r, "Error checking %s for Btrfs filesystem: %m", swap->device);
|
||||||
if (btrfs > 0) {
|
if (r > 0) {
|
||||||
log_debug("%s: detection of swap file offset on Btrfs is not supported", swap->device);
|
log_debug("%s: detection of swap file offset on Btrfs is not supported", swap->device);
|
||||||
*ret_offset = UINT64_MAX;
|
*ret_offset = UINT64_MAX;
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -42,19 +42,10 @@ TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Marshal)(TPM2B_PUBLIC const *src, uint8_t buf
|
|||||||
TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal)(uint8_t const buffer[], size_t buffer_size, size_t *offset, TPM2B_PUBLIC *dest) = NULL;
|
TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal)(uint8_t const buffer[], size_t buffer_size, size_t *offset, TPM2B_PUBLIC *dest) = NULL;
|
||||||
|
|
||||||
int dlopen_tpm2(void) {
|
int dlopen_tpm2(void) {
|
||||||
int r, k = 0;
|
int r;
|
||||||
|
|
||||||
if (!libtss2_esys_dl) {
|
r = dlopen_many_sym_or_warn(
|
||||||
_cleanup_(dlclosep) void *dl = NULL;
|
&libtss2_esys_dl, "libtss2-esys.so.0", LOG_DEBUG,
|
||||||
|
|
||||||
dl = dlopen("libtss2-esys.so.0", RTLD_LAZY);
|
|
||||||
if (!dl)
|
|
||||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
|
||||||
"TPM2 support is not installed: %s", dlerror());
|
|
||||||
|
|
||||||
r = dlsym_many_and_warn(
|
|
||||||
dl,
|
|
||||||
LOG_DEBUG,
|
|
||||||
DLSYM_ARG(Esys_Create),
|
DLSYM_ARG(Esys_Create),
|
||||||
DLSYM_ARG(Esys_CreatePrimary),
|
DLSYM_ARG(Esys_CreatePrimary),
|
||||||
DLSYM_ARG(Esys_Finalize),
|
DLSYM_ARG(Esys_Finalize),
|
||||||
@ -67,59 +58,22 @@ int dlopen_tpm2(void) {
|
|||||||
DLSYM_ARG(Esys_PolicyPCR),
|
DLSYM_ARG(Esys_PolicyPCR),
|
||||||
DLSYM_ARG(Esys_StartAuthSession),
|
DLSYM_ARG(Esys_StartAuthSession),
|
||||||
DLSYM_ARG(Esys_Startup),
|
DLSYM_ARG(Esys_Startup),
|
||||||
DLSYM_ARG(Esys_Unseal),
|
DLSYM_ARG(Esys_Unseal));
|
||||||
NULL);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
libtss2_esys_dl = TAKE_PTR(dl);
|
r = dlopen_many_sym_or_warn(
|
||||||
k++;
|
&libtss2_rc_dl, "libtss2-rc.so.0", LOG_DEBUG,
|
||||||
}
|
DLSYM_ARG(Tss2_RC_Decode));
|
||||||
|
|
||||||
if (!libtss2_rc_dl) {
|
|
||||||
_cleanup_(dlclosep) void *dl = NULL;
|
|
||||||
|
|
||||||
dl = dlopen("libtss2-rc.so.0", RTLD_LAZY);
|
|
||||||
if (!dl)
|
|
||||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
|
||||||
"TPM2 support is not installed: %s", dlerror());
|
|
||||||
|
|
||||||
r = dlsym_many_and_warn(
|
|
||||||
dl,
|
|
||||||
LOG_DEBUG,
|
|
||||||
DLSYM_ARG(Tss2_RC_Decode),
|
|
||||||
NULL);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
libtss2_rc_dl = TAKE_PTR(dl);
|
return dlopen_many_sym_or_warn(
|
||||||
k++;
|
&libtss2_mu_dl, "libtss2-mu.so.0", LOG_DEBUG,
|
||||||
}
|
|
||||||
|
|
||||||
if (!libtss2_mu_dl) {
|
|
||||||
_cleanup_(dlclosep) void *dl = NULL;
|
|
||||||
|
|
||||||
dl = dlopen("libtss2-mu.so.0", RTLD_LAZY);
|
|
||||||
if (!dl)
|
|
||||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
|
||||||
"TPM2 support is not installed: %s", dlerror());
|
|
||||||
|
|
||||||
r = dlsym_many_and_warn(
|
|
||||||
dl,
|
|
||||||
LOG_DEBUG,
|
|
||||||
DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Marshal),
|
DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Marshal),
|
||||||
DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Unmarshal),
|
DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Unmarshal),
|
||||||
DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Marshal),
|
DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Marshal),
|
||||||
DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Unmarshal),
|
DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Unmarshal));
|
||||||
NULL);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
libtss2_mu_dl = TAKE_PTR(dl);
|
|
||||||
k++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return k;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tpm2_context {
|
struct tpm2_context {
|
||||||
|
|||||||
@ -146,6 +146,8 @@ tests += [
|
|||||||
|
|
||||||
[['src/test/test-utf8.c']],
|
[['src/test/test-utf8.c']],
|
||||||
|
|
||||||
|
[['src/test/test-blockdev-util.c']],
|
||||||
|
|
||||||
[['src/test/test-dev-setup.c']],
|
[['src/test/test-dev-setup.c']],
|
||||||
|
|
||||||
[['src/test/test-capability.c'],
|
[['src/test/test-capability.c'],
|
||||||
@ -159,6 +161,8 @@ tests += [
|
|||||||
|
|
||||||
[['src/test/test-copy.c']],
|
[['src/test/test-copy.c']],
|
||||||
|
|
||||||
|
[['src/test/test-data-fd-util.c']],
|
||||||
|
|
||||||
[['src/test/test-static-destruct.c']],
|
[['src/test/test-static-destruct.c']],
|
||||||
|
|
||||||
[['src/test/test-sigbus.c']],
|
[['src/test/test-sigbus.c']],
|
||||||
@ -366,6 +370,8 @@ tests += [
|
|||||||
[],
|
[],
|
||||||
[threads]],
|
[threads]],
|
||||||
|
|
||||||
|
[['src/test/test-hash-funcs.c']],
|
||||||
|
|
||||||
[['src/test/test-bitmap.c']],
|
[['src/test/test-bitmap.c']],
|
||||||
|
|
||||||
[['src/test/test-xml.c']],
|
[['src/test/test-xml.c']],
|
||||||
|
|||||||
43
src/test/test-blockdev-util.c
Normal file
43
src/test/test-blockdev-util.c
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
#include "blockdev-util.h"
|
||||||
|
#include "errno-util.h"
|
||||||
|
#include "tests.h"
|
||||||
|
|
||||||
|
static void test_path_is_encrypted_one(const char *p, int expect) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = path_is_encrypted(p);
|
||||||
|
if (r == -ENOENT || ERRNO_IS_PRIVILEGE(r)) /* This might fail, if btrfs is used and we run in a
|
||||||
|
* container. In that case we cannot resolve the device node paths that
|
||||||
|
* BTRFS_IOC_DEV_INFO returns, because the device nodes are unlikely to exist in
|
||||||
|
* the container. But if we can't stat() them we cannot determine the dev_t of
|
||||||
|
* them, and thus cannot figure out if they are enrypted. Hence let's just ignore
|
||||||
|
* ENOENT here. Also skip the test if we lack privileges. */
|
||||||
|
return;
|
||||||
|
assert_se(r >= 0);
|
||||||
|
|
||||||
|
log_info("%s encrypted: %s", p, yes_no(r));
|
||||||
|
|
||||||
|
assert_se(expect < 0 || ((r > 0) == (expect > 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_path_is_encrypted(void) {
|
||||||
|
int booted = sd_booted(); /* If this is run in build environments such as koji, /dev might be a
|
||||||
|
* reguar fs. Don't assume too much if not running under systemd. */
|
||||||
|
|
||||||
|
log_info("/* %s (sd_booted=%d) */", __func__, booted);
|
||||||
|
|
||||||
|
test_path_is_encrypted_one("/home", -1);
|
||||||
|
test_path_is_encrypted_one("/var", -1);
|
||||||
|
test_path_is_encrypted_one("/", -1);
|
||||||
|
test_path_is_encrypted_one("/proc", false);
|
||||||
|
test_path_is_encrypted_one("/sys", false);
|
||||||
|
test_path_is_encrypted_one("/dev", booted > 0 ? false : -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
test_setup_logging(LOG_INFO);
|
||||||
|
|
||||||
|
test_path_is_encrypted();
|
||||||
|
}
|
||||||
154
src/test/test-data-fd-util.c
Normal file
154
src/test/test-data-fd-util.c
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "data-fd-util.h"
|
||||||
|
#include "fd-util.h"
|
||||||
|
#include "memory-util.h"
|
||||||
|
#include "process-util.h"
|
||||||
|
#include "tests.h"
|
||||||
|
#include "random-util.h"
|
||||||
|
|
||||||
|
static void test_acquire_data_fd_one(unsigned flags) {
|
||||||
|
char wbuffer[196*1024 - 7];
|
||||||
|
char rbuffer[sizeof(wbuffer)];
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = acquire_data_fd("foo", 3, flags);
|
||||||
|
assert_se(fd >= 0);
|
||||||
|
|
||||||
|
zero(rbuffer);
|
||||||
|
assert_se(read(fd, rbuffer, sizeof(rbuffer)) == 3);
|
||||||
|
assert_se(streq(rbuffer, "foo"));
|
||||||
|
|
||||||
|
fd = safe_close(fd);
|
||||||
|
|
||||||
|
fd = acquire_data_fd("", 0, flags);
|
||||||
|
assert_se(fd >= 0);
|
||||||
|
|
||||||
|
zero(rbuffer);
|
||||||
|
assert_se(read(fd, rbuffer, sizeof(rbuffer)) == 0);
|
||||||
|
assert_se(streq(rbuffer, ""));
|
||||||
|
|
||||||
|
fd = safe_close(fd);
|
||||||
|
|
||||||
|
random_bytes(wbuffer, sizeof(wbuffer));
|
||||||
|
|
||||||
|
fd = acquire_data_fd(wbuffer, sizeof(wbuffer), flags);
|
||||||
|
assert_se(fd >= 0);
|
||||||
|
|
||||||
|
zero(rbuffer);
|
||||||
|
assert_se(read(fd, rbuffer, sizeof(rbuffer)) == sizeof(rbuffer));
|
||||||
|
assert_se(memcmp(rbuffer, wbuffer, sizeof(rbuffer)) == 0);
|
||||||
|
|
||||||
|
fd = safe_close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_acquire_data_fd(void) {
|
||||||
|
test_acquire_data_fd_one(0);
|
||||||
|
test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL);
|
||||||
|
test_acquire_data_fd_one(ACQUIRE_NO_MEMFD);
|
||||||
|
test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD);
|
||||||
|
test_acquire_data_fd_one(ACQUIRE_NO_PIPE);
|
||||||
|
test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_PIPE);
|
||||||
|
test_acquire_data_fd_one(ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE);
|
||||||
|
test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE);
|
||||||
|
test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE|ACQUIRE_NO_TMPFILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assert_equal_fd(int fd1, int fd2) {
|
||||||
|
for (;;) {
|
||||||
|
uint8_t a[4096], b[4096];
|
||||||
|
ssize_t x, y;
|
||||||
|
|
||||||
|
x = read(fd1, a, sizeof(a));
|
||||||
|
assert_se(x >= 0);
|
||||||
|
|
||||||
|
y = read(fd2, b, sizeof(b));
|
||||||
|
assert_se(y >= 0);
|
||||||
|
|
||||||
|
assert_se(x == y);
|
||||||
|
|
||||||
|
if (x == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
assert_se(memcmp(a, b, x) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_copy_data_fd(void) {
|
||||||
|
_cleanup_close_ int fd1 = -1, fd2 = -1;
|
||||||
|
_cleanup_(close_pairp) int sfd[2] = { -1, -1 };
|
||||||
|
_cleanup_(sigkill_waitp) pid_t pid = -1;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
fd1 = open("/etc/fstab", O_RDONLY|O_CLOEXEC);
|
||||||
|
if (fd1 >= 0) {
|
||||||
|
|
||||||
|
fd2 = copy_data_fd(fd1);
|
||||||
|
assert_se(fd2 >= 0);
|
||||||
|
|
||||||
|
assert_se(lseek(fd1, 0, SEEK_SET) == 0);
|
||||||
|
assert_equal_fd(fd1, fd2);
|
||||||
|
}
|
||||||
|
|
||||||
|
fd1 = safe_close(fd1);
|
||||||
|
fd2 = safe_close(fd2);
|
||||||
|
|
||||||
|
fd1 = acquire_data_fd("hallo", 6, 0);
|
||||||
|
assert_se(fd1 >= 0);
|
||||||
|
|
||||||
|
fd2 = copy_data_fd(fd1);
|
||||||
|
assert_se(fd2 >= 0);
|
||||||
|
|
||||||
|
safe_close(fd1);
|
||||||
|
fd1 = acquire_data_fd("hallo", 6, 0);
|
||||||
|
assert_se(fd1 >= 0);
|
||||||
|
|
||||||
|
assert_equal_fd(fd1, fd2);
|
||||||
|
|
||||||
|
fd1 = safe_close(fd1);
|
||||||
|
fd2 = safe_close(fd2);
|
||||||
|
|
||||||
|
assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sfd) >= 0);
|
||||||
|
|
||||||
|
r = safe_fork("(sd-pipe)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
|
||||||
|
assert_se(r >= 0);
|
||||||
|
|
||||||
|
if (r == 0) {
|
||||||
|
/* child */
|
||||||
|
|
||||||
|
sfd[0] = safe_close(sfd[0]);
|
||||||
|
|
||||||
|
for (uint64_t i = 0; i < 1536*1024 / sizeof(uint64_t); i++)
|
||||||
|
assert_se(write(sfd[1], &i, sizeof(i)) == sizeof(i));
|
||||||
|
|
||||||
|
sfd[1] = safe_close(sfd[1]);
|
||||||
|
|
||||||
|
_exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
sfd[1] = safe_close(sfd[1]);
|
||||||
|
|
||||||
|
fd2 = copy_data_fd(sfd[0]);
|
||||||
|
assert_se(fd2 >= 0);
|
||||||
|
|
||||||
|
uint64_t j;
|
||||||
|
for (uint64_t i = 0; i < 1536*1024 / sizeof(uint64_t); i++) {
|
||||||
|
assert_se(read(fd2, &j, sizeof(j)) == sizeof(j));
|
||||||
|
assert_se(i == j);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_se(read(fd2, &j, sizeof(j)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
test_setup_logging(LOG_DEBUG);
|
||||||
|
|
||||||
|
test_acquire_data_fd();
|
||||||
|
test_copy_data_fd();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
|
#include "data-fd-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
@ -95,54 +96,6 @@ static void test_open_serialization_fd(void) {
|
|||||||
assert_se(write(fd, "test\n", 5) == 5);
|
assert_se(write(fd, "test\n", 5) == 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_acquire_data_fd_one(unsigned flags) {
|
|
||||||
char wbuffer[196*1024 - 7];
|
|
||||||
char rbuffer[sizeof(wbuffer)];
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
fd = acquire_data_fd("foo", 3, flags);
|
|
||||||
assert_se(fd >= 0);
|
|
||||||
|
|
||||||
zero(rbuffer);
|
|
||||||
assert_se(read(fd, rbuffer, sizeof(rbuffer)) == 3);
|
|
||||||
assert_se(streq(rbuffer, "foo"));
|
|
||||||
|
|
||||||
fd = safe_close(fd);
|
|
||||||
|
|
||||||
fd = acquire_data_fd("", 0, flags);
|
|
||||||
assert_se(fd >= 0);
|
|
||||||
|
|
||||||
zero(rbuffer);
|
|
||||||
assert_se(read(fd, rbuffer, sizeof(rbuffer)) == 0);
|
|
||||||
assert_se(streq(rbuffer, ""));
|
|
||||||
|
|
||||||
fd = safe_close(fd);
|
|
||||||
|
|
||||||
random_bytes(wbuffer, sizeof(wbuffer));
|
|
||||||
|
|
||||||
fd = acquire_data_fd(wbuffer, sizeof(wbuffer), flags);
|
|
||||||
assert_se(fd >= 0);
|
|
||||||
|
|
||||||
zero(rbuffer);
|
|
||||||
assert_se(read(fd, rbuffer, sizeof(rbuffer)) == sizeof(rbuffer));
|
|
||||||
assert_se(memcmp(rbuffer, wbuffer, sizeof(rbuffer)) == 0);
|
|
||||||
|
|
||||||
fd = safe_close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_acquire_data_fd(void) {
|
|
||||||
|
|
||||||
test_acquire_data_fd_one(0);
|
|
||||||
test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL);
|
|
||||||
test_acquire_data_fd_one(ACQUIRE_NO_MEMFD);
|
|
||||||
test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD);
|
|
||||||
test_acquire_data_fd_one(ACQUIRE_NO_PIPE);
|
|
||||||
test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_PIPE);
|
|
||||||
test_acquire_data_fd_one(ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE);
|
|
||||||
test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE);
|
|
||||||
test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE|ACQUIRE_NO_TMPFILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_fd_move_above_stdio(void) {
|
static void test_fd_move_above_stdio(void) {
|
||||||
int original_stdin, new_fd;
|
int original_stdin, new_fd;
|
||||||
|
|
||||||
@ -227,93 +180,6 @@ static void test_rearrange_stdio(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void assert_equal_fd(int fd1, int fd2) {
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
uint8_t a[4096], b[4096];
|
|
||||||
ssize_t x, y;
|
|
||||||
|
|
||||||
x = read(fd1, a, sizeof(a));
|
|
||||||
assert_se(x >= 0);
|
|
||||||
|
|
||||||
y = read(fd2, b, sizeof(b));
|
|
||||||
assert_se(y >= 0);
|
|
||||||
|
|
||||||
assert_se(x == y);
|
|
||||||
|
|
||||||
if (x == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
assert_se(memcmp(a, b, x) == 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_fd_duplicate_data_fd(void) {
|
|
||||||
_cleanup_close_ int fd1 = -1, fd2 = -1;
|
|
||||||
_cleanup_(close_pairp) int sfd[2] = { -1, -1 };
|
|
||||||
_cleanup_(sigkill_waitp) pid_t pid = -1;
|
|
||||||
uint64_t i, j;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
fd1 = open("/etc/fstab", O_RDONLY|O_CLOEXEC);
|
|
||||||
if (fd1 >= 0) {
|
|
||||||
|
|
||||||
fd2 = fd_duplicate_data_fd(fd1);
|
|
||||||
assert_se(fd2 >= 0);
|
|
||||||
|
|
||||||
assert_se(lseek(fd1, 0, SEEK_SET) == 0);
|
|
||||||
assert_equal_fd(fd1, fd2);
|
|
||||||
}
|
|
||||||
|
|
||||||
fd1 = safe_close(fd1);
|
|
||||||
fd2 = safe_close(fd2);
|
|
||||||
|
|
||||||
fd1 = acquire_data_fd("hallo", 6, 0);
|
|
||||||
assert_se(fd1 >= 0);
|
|
||||||
|
|
||||||
fd2 = fd_duplicate_data_fd(fd1);
|
|
||||||
assert_se(fd2 >= 0);
|
|
||||||
|
|
||||||
safe_close(fd1);
|
|
||||||
fd1 = acquire_data_fd("hallo", 6, 0);
|
|
||||||
assert_se(fd1 >= 0);
|
|
||||||
|
|
||||||
assert_equal_fd(fd1, fd2);
|
|
||||||
|
|
||||||
fd1 = safe_close(fd1);
|
|
||||||
fd2 = safe_close(fd2);
|
|
||||||
|
|
||||||
assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sfd) >= 0);
|
|
||||||
|
|
||||||
r = safe_fork("(sd-pipe)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
|
|
||||||
assert_se(r >= 0);
|
|
||||||
|
|
||||||
if (r == 0) {
|
|
||||||
/* child */
|
|
||||||
|
|
||||||
sfd[0] = safe_close(sfd[0]);
|
|
||||||
|
|
||||||
for (i = 0; i < 1536*1024 / sizeof(uint64_t); i++)
|
|
||||||
assert_se(write(sfd[1], &i, sizeof(i)) == sizeof(i));
|
|
||||||
|
|
||||||
sfd[1] = safe_close(sfd[1]);
|
|
||||||
|
|
||||||
_exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
sfd[1] = safe_close(sfd[1]);
|
|
||||||
|
|
||||||
fd2 = fd_duplicate_data_fd(sfd[0]);
|
|
||||||
assert_se(fd2 >= 0);
|
|
||||||
|
|
||||||
for (i = 0; i < 1536*1024 / sizeof(uint64_t); i++) {
|
|
||||||
assert_se(read(fd2, &j, sizeof(j)) == sizeof(j));
|
|
||||||
assert_se(i == j);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_se(read(fd2, &j, sizeof(j)) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_read_nr_open(void) {
|
static void test_read_nr_open(void) {
|
||||||
log_info("nr-open: %i", read_nr_open());
|
log_info("nr-open: %i", read_nr_open());
|
||||||
}
|
}
|
||||||
@ -420,10 +286,8 @@ int main(int argc, char *argv[]) {
|
|||||||
test_close_nointr();
|
test_close_nointr();
|
||||||
test_same_fd();
|
test_same_fd();
|
||||||
test_open_serialization_fd();
|
test_open_serialization_fd();
|
||||||
test_acquire_data_fd();
|
|
||||||
test_fd_move_above_stdio();
|
test_fd_move_above_stdio();
|
||||||
test_rearrange_stdio();
|
test_rearrange_stdio();
|
||||||
test_fd_duplicate_data_fd();
|
|
||||||
test_read_nr_open();
|
test_read_nr_open();
|
||||||
test_close_all_fds();
|
test_close_all_fds();
|
||||||
|
|
||||||
|
|||||||
@ -805,38 +805,6 @@ static void test_chmod_and_chown(void) {
|
|||||||
assert_se(S_ISLNK(st.st_mode));
|
assert_se(S_ISLNK(st.st_mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_path_is_encrypted_one(const char *p, int expect) {
|
|
||||||
int r;
|
|
||||||
|
|
||||||
r = path_is_encrypted(p);
|
|
||||||
if (r == -ENOENT || ERRNO_IS_PRIVILEGE(r)) /* This might fail, if btrfs is used and we run in a
|
|
||||||
* container. In that case we cannot resolve the device node paths that
|
|
||||||
* BTRFS_IOC_DEV_INFO returns, because the device nodes are unlikely to exist in
|
|
||||||
* the container. But if we can't stat() them we cannot determine the dev_t of
|
|
||||||
* them, and thus cannot figure out if they are enrypted. Hence let's just ignore
|
|
||||||
* ENOENT here. Also skip the test if we lack privileges. */
|
|
||||||
return;
|
|
||||||
assert_se(r >= 0);
|
|
||||||
|
|
||||||
log_info("%s encrypted: %s", p, yes_no(r));
|
|
||||||
|
|
||||||
assert_se(expect < 0 || ((r > 0) == (expect > 0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_path_is_encrypted(void) {
|
|
||||||
int booted = sd_booted(); /* If this is run in build environments such as koji, /dev might be a
|
|
||||||
* reguar fs. Don't assume too much if not running under systemd. */
|
|
||||||
|
|
||||||
log_info("/* %s (sd_booted=%d) */", __func__, booted);
|
|
||||||
|
|
||||||
test_path_is_encrypted_one("/home", -1);
|
|
||||||
test_path_is_encrypted_one("/var", -1);
|
|
||||||
test_path_is_encrypted_one("/", -1);
|
|
||||||
test_path_is_encrypted_one("/proc", false);
|
|
||||||
test_path_is_encrypted_one("/sys", false);
|
|
||||||
test_path_is_encrypted_one("/dev", booted > 0 ? false : -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void create_binary_file(const char *p, const void *data, size_t l) {
|
static void create_binary_file(const char *p, const void *data, size_t l) {
|
||||||
_cleanup_close_ int fd = -1;
|
_cleanup_close_ int fd = -1;
|
||||||
|
|
||||||
@ -914,7 +882,6 @@ int main(int argc, char *argv[]) {
|
|||||||
test_fsync_directory_of_file();
|
test_fsync_directory_of_file();
|
||||||
test_rename_noreplace();
|
test_rename_noreplace();
|
||||||
test_chmod_and_chown();
|
test_chmod_and_chown();
|
||||||
test_path_is_encrypted();
|
|
||||||
test_conservative_rename();
|
test_conservative_rename();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
83
src/test/test-hash-funcs.c
Normal file
83
src/test/test-hash-funcs.c
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
#include "tests.h"
|
||||||
|
#include "hash-funcs.h"
|
||||||
|
#include "set.h"
|
||||||
|
|
||||||
|
static void test_path_hash_set(void) {
|
||||||
|
/* The goal is to make sure that non-simplified path are hashed as expected,
|
||||||
|
* and that we don't need to simplify them beforehand. */
|
||||||
|
|
||||||
|
log_info("/* %s */", __func__);
|
||||||
|
|
||||||
|
/* No freeing of keys, we operate on static strings here… */
|
||||||
|
_cleanup_set_free_ Set *set = NULL;
|
||||||
|
|
||||||
|
assert_se(set_isempty(set));
|
||||||
|
assert_se(set_ensure_put(&set, &path_hash_ops, "foo") == 1);
|
||||||
|
assert_se(set_ensure_put(&set, &path_hash_ops, "foo") == 0);
|
||||||
|
assert_se(set_ensure_put(&set, &path_hash_ops, "bar") == 1);
|
||||||
|
assert_se(set_ensure_put(&set, &path_hash_ops, "bar") == 0);
|
||||||
|
assert_se(set_ensure_put(&set, &path_hash_ops, "/foo") == 1);
|
||||||
|
assert_se(set_ensure_put(&set, &path_hash_ops, "/bar") == 1);
|
||||||
|
assert_se(set_ensure_put(&set, &path_hash_ops, "/foo/.") == 0);
|
||||||
|
assert_se(set_ensure_put(&set, &path_hash_ops, "/./bar/./.") == 0);
|
||||||
|
|
||||||
|
assert_se(set_contains(set, "foo"));
|
||||||
|
assert_se(set_contains(set, "bar"));
|
||||||
|
assert_se(set_contains(set, "./foo"));
|
||||||
|
assert_se(set_contains(set, "./foo/."));
|
||||||
|
assert_se(set_contains(set, "./bar"));
|
||||||
|
assert_se(set_contains(set, "./bar/."));
|
||||||
|
assert_se(set_contains(set, "/foo"));
|
||||||
|
assert_se(set_contains(set, "/bar"));
|
||||||
|
assert_se(set_contains(set, "//./foo"));
|
||||||
|
assert_se(set_contains(set, "///./foo/."));
|
||||||
|
assert_se(set_contains(set, "////./bar"));
|
||||||
|
assert_se(set_contains(set, "/////./bar/."));
|
||||||
|
|
||||||
|
assert_se(set_contains(set, "foo/"));
|
||||||
|
assert_se(set_contains(set, "bar/"));
|
||||||
|
assert_se(set_contains(set, "./foo/"));
|
||||||
|
assert_se(set_contains(set, "./foo/./"));
|
||||||
|
assert_se(set_contains(set, "./bar/"));
|
||||||
|
assert_se(set_contains(set, "./bar/./"));
|
||||||
|
assert_se(set_contains(set, "/foo/"));
|
||||||
|
assert_se(set_contains(set, "/bar/"));
|
||||||
|
assert_se(set_contains(set, "//./foo/"));
|
||||||
|
assert_se(set_contains(set, "///./foo/./"));
|
||||||
|
assert_se(set_contains(set, "////./bar/"));
|
||||||
|
assert_se(set_contains(set, "/////./bar/./"));
|
||||||
|
|
||||||
|
assert_se(!set_contains(set, "foo."));
|
||||||
|
assert_se(!set_contains(set, ".bar"));
|
||||||
|
assert_se(!set_contains(set, "./foo."));
|
||||||
|
assert_se(!set_contains(set, "./.foo/."));
|
||||||
|
assert_se(!set_contains(set, "../bar"));
|
||||||
|
assert_se(!set_contains(set, "./bar/.."));
|
||||||
|
assert_se(!set_contains(set, "./foo.."));
|
||||||
|
assert_se(!set_contains(set, "/..bar"));
|
||||||
|
assert_se(!set_contains(set, "//../foo"));
|
||||||
|
assert_se(!set_contains(set, "///../foo/."));
|
||||||
|
assert_se(!set_contains(set, "////../bar"));
|
||||||
|
assert_se(!set_contains(set, "/////../bar/."));
|
||||||
|
|
||||||
|
assert_se(!set_contains(set, "foo./"));
|
||||||
|
assert_se(!set_contains(set, ".bar/"));
|
||||||
|
assert_se(!set_contains(set, "./foo./"));
|
||||||
|
assert_se(!set_contains(set, "./.foo/./"));
|
||||||
|
assert_se(!set_contains(set, "../bar/"));
|
||||||
|
assert_se(!set_contains(set, "./bar/../"));
|
||||||
|
assert_se(!set_contains(set, "./foo../"));
|
||||||
|
assert_se(!set_contains(set, "/..bar/"));
|
||||||
|
assert_se(!set_contains(set, "//../foo/"));
|
||||||
|
assert_se(!set_contains(set, "///../foo/./"));
|
||||||
|
assert_se(!set_contains(set, "////../bar/"));
|
||||||
|
assert_se(!set_contains(set, "/////../bar/./"));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
test_setup_logging(LOG_INFO);
|
||||||
|
|
||||||
|
test_path_hash_set();
|
||||||
|
}
|
||||||
@ -7,7 +7,9 @@
|
|||||||
#include "capability-util.h"
|
#include "capability-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
|
#include "fs-util.h"
|
||||||
#include "missing_mount.h"
|
#include "missing_mount.h"
|
||||||
|
#include "mkdir.h"
|
||||||
#include "mount-util.h"
|
#include "mount-util.h"
|
||||||
#include "namespace-util.h"
|
#include "namespace-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
@ -217,6 +219,52 @@ static void test_bind_remount_one(void) {
|
|||||||
assert_se(wait_for_terminate_and_check("test-remount-one", pid, WAIT_LOG) == EXIT_SUCCESS);
|
assert_se(wait_for_terminate_and_check("test-remount-one", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_make_mount_point_inode(void) {
|
||||||
|
_cleanup_(rm_rf_physical_and_freep) char *d = NULL;
|
||||||
|
const char *src_file, *src_dir, *dst_file, *dst_dir;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
log_info("/* %s */", __func__);
|
||||||
|
|
||||||
|
assert_se(mkdtemp_malloc(NULL, &d) >= 0);
|
||||||
|
|
||||||
|
src_file = strjoina(d, "/src/file");
|
||||||
|
src_dir = strjoina(d, "/src/dir");
|
||||||
|
dst_file = strjoina(d, "/dst/file");
|
||||||
|
dst_dir = strjoina(d, "/dst/dir");
|
||||||
|
|
||||||
|
assert_se(mkdir_p(src_dir, 0755) >= 0);
|
||||||
|
assert_se(mkdir_parents(dst_file, 0755) >= 0);
|
||||||
|
assert_se(touch(src_file) >= 0);
|
||||||
|
|
||||||
|
assert_se(make_mount_point_inode_from_path(src_file, dst_file, 0755) >= 0);
|
||||||
|
assert_se(make_mount_point_inode_from_path(src_dir, dst_dir, 0755) >= 0);
|
||||||
|
|
||||||
|
assert_se(stat(dst_dir, &st) == 0);
|
||||||
|
assert_se(S_ISDIR(st.st_mode));
|
||||||
|
assert_se(stat(dst_file, &st) == 0);
|
||||||
|
assert_se(S_ISREG(st.st_mode));
|
||||||
|
assert_se(!(S_IXUSR & st.st_mode));
|
||||||
|
assert_se(!(S_IXGRP & st.st_mode));
|
||||||
|
assert_se(!(S_IXOTH & st.st_mode));
|
||||||
|
|
||||||
|
assert_se(unlink(dst_file) == 0);
|
||||||
|
assert_se(rmdir(dst_dir) == 0);
|
||||||
|
|
||||||
|
assert_se(stat(src_file, &st) == 0);
|
||||||
|
assert_se(make_mount_point_inode_from_stat(&st, dst_file, 0755) >= 0);
|
||||||
|
assert_se(stat(src_dir, &st) == 0);
|
||||||
|
assert_se(make_mount_point_inode_from_stat(&st, dst_dir, 0755) >= 0);
|
||||||
|
|
||||||
|
assert_se(stat(dst_dir, &st) == 0);
|
||||||
|
assert_se(S_ISDIR(st.st_mode));
|
||||||
|
assert_se(stat(dst_file, &st) == 0);
|
||||||
|
assert_se(S_ISREG(st.st_mode));
|
||||||
|
assert_se(!(S_IXUSR & st.st_mode));
|
||||||
|
assert_se(!(S_IXGRP & st.st_mode));
|
||||||
|
assert_se(!(S_IXOTH & st.st_mode));
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
test_setup_logging(LOG_DEBUG);
|
test_setup_logging(LOG_DEBUG);
|
||||||
|
|
||||||
@ -224,6 +272,7 @@ int main(int argc, char *argv[]) {
|
|||||||
test_mount_flags_to_string();
|
test_mount_flags_to_string();
|
||||||
test_bind_remount_recursive();
|
test_bind_remount_recursive();
|
||||||
test_bind_remount_one();
|
test_bind_remount_one();
|
||||||
|
test_make_mount_point_inode();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,10 +8,8 @@
|
|||||||
#include "def.h"
|
#include "def.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "fs-util.h"
|
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "mkdir.h"
|
|
||||||
#include "mountpoint-util.h"
|
#include "mountpoint-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "rm-rf.h"
|
#include "rm-rf.h"
|
||||||
@ -290,52 +288,6 @@ static void test_fd_is_mount_point(void) {
|
|||||||
assert_se(IN_SET(fd_is_mount_point(fd, "root/", 0), -ENOENT, 0));
|
assert_se(IN_SET(fd_is_mount_point(fd, "root/", 0), -ENOENT, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_make_mount_point_inode(void) {
|
|
||||||
_cleanup_(rm_rf_physical_and_freep) char *d = NULL;
|
|
||||||
const char *src_file, *src_dir, *dst_file, *dst_dir;
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
log_info("/* %s */", __func__);
|
|
||||||
|
|
||||||
assert_se(mkdtemp_malloc(NULL, &d) >= 0);
|
|
||||||
|
|
||||||
src_file = strjoina(d, "/src/file");
|
|
||||||
src_dir = strjoina(d, "/src/dir");
|
|
||||||
dst_file = strjoina(d, "/dst/file");
|
|
||||||
dst_dir = strjoina(d, "/dst/dir");
|
|
||||||
|
|
||||||
assert_se(mkdir_p(src_dir, 0755) >= 0);
|
|
||||||
assert_se(mkdir_parents(dst_file, 0755) >= 0);
|
|
||||||
assert_se(touch(src_file) >= 0);
|
|
||||||
|
|
||||||
assert_se(make_mount_point_inode_from_path(src_file, dst_file, 0755) >= 0);
|
|
||||||
assert_se(make_mount_point_inode_from_path(src_dir, dst_dir, 0755) >= 0);
|
|
||||||
|
|
||||||
assert_se(stat(dst_dir, &st) == 0);
|
|
||||||
assert_se(S_ISDIR(st.st_mode));
|
|
||||||
assert_se(stat(dst_file, &st) == 0);
|
|
||||||
assert_se(S_ISREG(st.st_mode));
|
|
||||||
assert_se(!(S_IXUSR & st.st_mode));
|
|
||||||
assert_se(!(S_IXGRP & st.st_mode));
|
|
||||||
assert_se(!(S_IXOTH & st.st_mode));
|
|
||||||
|
|
||||||
assert_se(unlink(dst_file) == 0);
|
|
||||||
assert_se(rmdir(dst_dir) == 0);
|
|
||||||
|
|
||||||
assert_se(stat(src_file, &st) == 0);
|
|
||||||
assert_se(make_mount_point_inode_from_stat(&st, dst_file, 0755) >= 0);
|
|
||||||
assert_se(stat(src_dir, &st) == 0);
|
|
||||||
assert_se(make_mount_point_inode_from_stat(&st, dst_dir, 0755) >= 0);
|
|
||||||
|
|
||||||
assert_se(stat(dst_dir, &st) == 0);
|
|
||||||
assert_se(S_ISDIR(st.st_mode));
|
|
||||||
assert_se(stat(dst_file, &st) == 0);
|
|
||||||
assert_se(S_ISREG(st.st_mode));
|
|
||||||
assert_se(!(S_IXUSR & st.st_mode));
|
|
||||||
assert_se(!(S_IXGRP & st.st_mode));
|
|
||||||
assert_se(!(S_IXOTH & st.st_mode));
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
test_setup_logging(LOG_DEBUG);
|
test_setup_logging(LOG_DEBUG);
|
||||||
|
|
||||||
@ -360,7 +312,6 @@ int main(int argc, char *argv[]) {
|
|||||||
test_mnt_id();
|
test_mnt_id();
|
||||||
test_path_is_mount_point();
|
test_path_is_mount_point();
|
||||||
test_fd_is_mount_point();
|
test_fd_is_mount_point();
|
||||||
test_make_mount_point_inode();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -126,6 +126,8 @@ static void test_path_compare_one(const char *a, const char *b, int expected) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void test_path_compare(void) {
|
static void test_path_compare(void) {
|
||||||
|
log_info("/* %s */", __func__);
|
||||||
|
|
||||||
test_path_compare_one("/goo", "/goo", 0);
|
test_path_compare_one("/goo", "/goo", 0);
|
||||||
test_path_compare_one("/goo", "/goo", 0);
|
test_path_compare_one("/goo", "/goo", 0);
|
||||||
test_path_compare_one("//goo", "/goo", 0);
|
test_path_compare_one("//goo", "/goo", 0);
|
||||||
@ -138,6 +140,12 @@ static void test_path_compare(void) {
|
|||||||
test_path_compare_one("/x", "x/", 1);
|
test_path_compare_one("/x", "x/", 1);
|
||||||
test_path_compare_one("x/", "/", -1);
|
test_path_compare_one("x/", "/", -1);
|
||||||
test_path_compare_one("/x/./y", "x/y", 1);
|
test_path_compare_one("/x/./y", "x/y", 1);
|
||||||
|
test_path_compare_one("/x/./y", "/x/y", 0);
|
||||||
|
test_path_compare_one("/x/./././y", "/x/y/././.", 0);
|
||||||
|
test_path_compare_one("./x/./././y", "./x/y/././.", 0);
|
||||||
|
test_path_compare_one(".", "./.", 0);
|
||||||
|
test_path_compare_one(".", "././.", 0);
|
||||||
|
test_path_compare_one("./..", ".", 1);
|
||||||
test_path_compare_one("x/.y", "x/y", -1);
|
test_path_compare_one("x/.y", "x/y", -1);
|
||||||
test_path_compare_one("foo", "/foo", -1);
|
test_path_compare_one("foo", "/foo", -1);
|
||||||
test_path_compare_one("/foo", "/foo/bar", -1);
|
test_path_compare_one("/foo", "/foo/bar", -1);
|
||||||
|
|||||||
@ -126,8 +126,6 @@ static void test_get_process_cmdline(void) {
|
|||||||
FOREACH_DIRENT(de, d, return) {
|
FOREACH_DIRENT(de, d, return) {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
dirent_ensure_type(d, de);
|
|
||||||
|
|
||||||
if (de->d_type != DT_DIR)
|
if (de->d_type != DT_DIR)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,6 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@ -21,6 +20,7 @@
|
|||||||
#include "extract-word.h"
|
#include "extract-word.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
|
#include "parse-util.h"
|
||||||
#include "scsi_id.h"
|
#include "scsi_id.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
@ -58,12 +58,10 @@ static char revision_str[16];
|
|||||||
static char type_str[16];
|
static char type_str[16];
|
||||||
|
|
||||||
static void set_type(const char *from, char *to, size_t len) {
|
static void set_type(const char *from, char *to, size_t len) {
|
||||||
int type_num;
|
unsigned type_num;
|
||||||
char *eptr;
|
|
||||||
const char *type = "generic";
|
const char *type = "generic";
|
||||||
|
|
||||||
type_num = strtoul(from, &eptr, 0);
|
if (safe_atou_full(from, 16, &type_num) >= 0) {
|
||||||
if (eptr != from) {
|
|
||||||
switch (type_num) {
|
switch (type_num) {
|
||||||
case 0:
|
case 0:
|
||||||
type = "disk";
|
type = "disk";
|
||||||
|
|||||||
@ -9,7 +9,6 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <linux/limits.h>
|
#include <linux/limits.h>
|
||||||
|
|
||||||
@ -83,6 +82,7 @@ static void get_cap_mask(sd_device *pdev, const char* attr,
|
|||||||
unsigned i;
|
unsigned i;
|
||||||
char* word;
|
char* word;
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
|
int r;
|
||||||
|
|
||||||
if (sd_device_get_sysattr_value(pdev, attr, &v) < 0)
|
if (sd_device_get_sysattr_value(pdev, attr, &v) < 0)
|
||||||
v = "";
|
v = "";
|
||||||
@ -93,16 +93,20 @@ static void get_cap_mask(sd_device *pdev, const char* attr,
|
|||||||
memzero(bitmask, bitmask_size);
|
memzero(bitmask, bitmask_size);
|
||||||
i = 0;
|
i = 0;
|
||||||
while ((word = strrchr(text, ' ')) != NULL) {
|
while ((word = strrchr(text, ' ')) != NULL) {
|
||||||
val = strtoul(word+1, NULL, 16);
|
r = safe_atolu_full(word+1, 16, &val);
|
||||||
if (i < bitmask_size / sizeof(unsigned long))
|
if (r < 0)
|
||||||
|
log_device_debug_errno(pdev, r, "Ignoring %s block which failed to parse: %m", attr);
|
||||||
|
else if (i < bitmask_size / sizeof(unsigned long))
|
||||||
bitmask[i] = val;
|
bitmask[i] = val;
|
||||||
else
|
else
|
||||||
log_device_debug(pdev, "Ignoring %s block %lX which is larger than maximum size", attr, val);
|
log_device_debug(pdev, "Ignoring %s block %lX which is larger than maximum size", attr, val);
|
||||||
*word = '\0';
|
*word = '\0';
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
val = strtoul (text, NULL, 16);
|
r = safe_atolu_full(text, 16, &val);
|
||||||
if (i < bitmask_size / sizeof(unsigned long))
|
if (r < 0)
|
||||||
|
log_device_debug_errno(pdev, r, "Ignoring %s block which failed to parse: %m", attr);
|
||||||
|
else if (i < bitmask_size / sizeof(unsigned long))
|
||||||
bitmask[i] = val;
|
bitmask[i] = val;
|
||||||
else
|
else
|
||||||
log_device_debug(pdev, "Ignoring %s block %lX which is larger than maximum size", attr, val);
|
log_device_debug(pdev, "Ignoring %s block %lX which is larger than maximum size", attr, val);
|
||||||
|
|||||||
@ -60,19 +60,19 @@ static int map_keycode(sd_device *dev, int fd, int scancode, const char *keycode
|
|||||||
unsigned scan;
|
unsigned scan;
|
||||||
unsigned key;
|
unsigned key;
|
||||||
} map;
|
} map;
|
||||||
char *endptr;
|
|
||||||
const struct key_name *k;
|
const struct key_name *k;
|
||||||
unsigned keycode_num;
|
unsigned keycode_num;
|
||||||
|
int r;
|
||||||
|
|
||||||
/* translate identifier to key code */
|
/* translate identifier to key code */
|
||||||
k = keyboard_lookup_key(keycode, strlen(keycode));
|
k = keyboard_lookup_key(keycode, strlen(keycode));
|
||||||
if (k) {
|
if (k)
|
||||||
keycode_num = k->id;
|
keycode_num = k->id;
|
||||||
} else {
|
else {
|
||||||
/* check if it's a numeric code already */
|
/* check if it's a numeric code already */
|
||||||
keycode_num = strtoul(keycode, &endptr, 0);
|
r = safe_atou(keycode, &keycode_num);
|
||||||
if (endptr[0] !='\0')
|
if (r < 0)
|
||||||
return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Failed to parse key identifier '%s'", keycode);
|
return log_device_error_errno(dev, r, "Failed to parse key identifier '%s': %m", keycode);
|
||||||
}
|
}
|
||||||
|
|
||||||
map.scan = scancode;
|
map.scan = scancode;
|
||||||
@ -170,17 +170,15 @@ static int builtin_keyboard(sd_device *dev, int argc, char *argv[], bool test) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_device_error_errno(dev, r, "Failed to get device name: %m");
|
return log_device_error_errno(dev, r, "Failed to get device name: %m");
|
||||||
|
|
||||||
FOREACH_DEVICE_PROPERTY(dev, key, value) {
|
FOREACH_DEVICE_PROPERTY(dev, key, value)
|
||||||
char *endptr;
|
|
||||||
|
|
||||||
if (startswith(key, "KEYBOARD_KEY_")) {
|
if (startswith(key, "KEYBOARD_KEY_")) {
|
||||||
const char *keycode = value;
|
const char *keycode = value;
|
||||||
unsigned scancode;
|
unsigned scancode;
|
||||||
|
|
||||||
/* KEYBOARD_KEY_<hex scan code>=<key identifier string> */
|
/* KEYBOARD_KEY_<hex scan code>=<key identifier string> */
|
||||||
scancode = strtoul(key + 13, &endptr, 16);
|
r = safe_atou_full(key + 13, 16, &scancode);
|
||||||
if (endptr[0] != '\0') {
|
if (r < 0) {
|
||||||
log_device_warning(dev, "Failed to parse scan code from \"%s\", ignoring", key);
|
log_device_warning_errno(dev, r, "Failed to parse scan code from \"%s\", ignoring: %m", key);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,9 +205,9 @@ static int builtin_keyboard(sd_device *dev, int argc, char *argv[], bool test) {
|
|||||||
unsigned evcode;
|
unsigned evcode;
|
||||||
|
|
||||||
/* EVDEV_ABS_<EV_ABS code>=<min>:<max>:<res>:<fuzz>:<flat> */
|
/* EVDEV_ABS_<EV_ABS code>=<min>:<max>:<res>:<fuzz>:<flat> */
|
||||||
evcode = strtoul(key + 10, &endptr, 16);
|
r = safe_atou_full(key + 10, 16, &evcode);
|
||||||
if (endptr[0] != '\0') {
|
if (r < 0) {
|
||||||
log_device_warning(dev, "Failed to parse EV_ABS code from \"%s\", ignoring", key);
|
log_device_warning_errno(dev, r, "Failed to parse EV_ABS code from \"%s\", ignoring: %m", key);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,7 +236,6 @@ static int builtin_keyboard(sd_device *dev, int argc, char *argv[], bool test) {
|
|||||||
(void) override_abs(dev, fd, evcode, value);
|
(void) override_abs(dev, fd, evcode, value);
|
||||||
} else if (streq(key, "POINTINGSTICK_SENSITIVITY"))
|
} else if (streq(key, "POINTINGSTICK_SENSITIVITY"))
|
||||||
(void) set_trackpoint_sensitivity(dev, value);
|
(void) set_trackpoint_sensitivity(dev, value);
|
||||||
}
|
|
||||||
|
|
||||||
/* install list of force-release codes */
|
/* install list of force-release codes */
|
||||||
if (release_count > 0)
|
if (release_count > 0)
|
||||||
|
|||||||
@ -17,7 +17,6 @@
|
|||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <net/if_arp.h>
|
#include <net/if_arp.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <linux/if.h>
|
#include <linux/if.h>
|
||||||
#include <linux/pci_regs.h>
|
#include <linux/pci_regs.h>
|
||||||
@ -199,8 +198,11 @@ static int dev_pci_onboard(sd_device *dev, struct netnames *names) {
|
|||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
/* kernel provided port index for multiple ports on a single PCI function */
|
/* kernel provided port index for multiple ports on a single PCI function */
|
||||||
if (sd_device_get_sysattr_value(dev, "dev_port", &attr) >= 0)
|
if (sd_device_get_sysattr_value(dev, "dev_port", &attr) >= 0) {
|
||||||
dev_port = strtoul(attr, NULL, 10);
|
r = safe_atolu_full(attr, 10, &dev_port);
|
||||||
|
if (r < 0)
|
||||||
|
log_device_debug_errno(dev, r, "Failed to parse dev_port, ignoring: %m");
|
||||||
|
}
|
||||||
|
|
||||||
/* kernel provided front panel port name for multiple port PCI device */
|
/* kernel provided front panel port name for multiple port PCI device */
|
||||||
(void) sd_device_get_sysattr_value(dev, "phys_port_name", &port_name);
|
(void) sd_device_get_sysattr_value(dev, "phys_port_name", &port_name);
|
||||||
@ -341,7 +343,9 @@ static int dev_pci_slot(sd_device *dev, struct netnames *names) {
|
|||||||
|
|
||||||
/* kernel provided port index for multiple ports on a single PCI function */
|
/* kernel provided port index for multiple ports on a single PCI function */
|
||||||
if (sd_device_get_sysattr_value(dev, "dev_port", &attr) >= 0) {
|
if (sd_device_get_sysattr_value(dev, "dev_port", &attr) >= 0) {
|
||||||
dev_port = strtoul(attr, NULL, 10);
|
r = safe_atolu_full(attr, 10, &dev_port);
|
||||||
|
if (r < 0)
|
||||||
|
log_device_debug_errno(dev, r, "Failed to parse attribute dev_port, ignoring: %m");
|
||||||
/* With older kernels IP-over-InfiniBand network interfaces sometimes erroneously
|
/* With older kernels IP-over-InfiniBand network interfaces sometimes erroneously
|
||||||
* provide the port number in the 'dev_id' sysfs attribute instead of 'dev_port',
|
* provide the port number in the 'dev_id' sysfs attribute instead of 'dev_port',
|
||||||
* which thus stays initialized as 0. */
|
* which thus stays initialized as 0. */
|
||||||
@ -349,10 +353,15 @@ static int dev_pci_slot(sd_device *dev, struct netnames *names) {
|
|||||||
sd_device_get_sysattr_value(dev, "type", &attr) >= 0) {
|
sd_device_get_sysattr_value(dev, "type", &attr) >= 0) {
|
||||||
unsigned long type;
|
unsigned long type;
|
||||||
|
|
||||||
type = strtoul(attr, NULL, 10);
|
r = safe_atolu_full(attr, 10, &type);
|
||||||
if (type == ARPHRD_INFINIBAND &&
|
if (r < 0)
|
||||||
sd_device_get_sysattr_value(dev, "dev_id", &attr) >= 0)
|
log_device_debug_errno(dev, r, "Failed to parse attribute type, ignoring: %m");
|
||||||
dev_port = strtoul(attr, NULL, 16);
|
else if (type == ARPHRD_INFINIBAND &&
|
||||||
|
sd_device_get_sysattr_value(dev, "dev_id", &attr) >= 0) {
|
||||||
|
r = safe_atolu_full(attr, 10, &dev_port);
|
||||||
|
if (r < 0)
|
||||||
|
log_device_debug_errno(dev, r, "Failed to parse attribute dev_id, ignoring: %m");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -765,7 +774,9 @@ static int names_mac(sd_device *dev, struct netnames *names) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
i = strtoul(s, NULL, 0);
|
r = safe_atolu_full(s, 10, &i);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
switch (i) {
|
switch (i) {
|
||||||
/* The persistent part of a hardware address of an InfiniBand NIC
|
/* The persistent part of a hardware address of an InfiniBand NIC
|
||||||
* is 8 bytes long. We cannot fit this much in an iface name.
|
* is 8 bytes long. We cannot fit this much in an iface name.
|
||||||
@ -780,7 +791,9 @@ static int names_mac(sd_device *dev, struct netnames *names) {
|
|||||||
r = sd_device_get_sysattr_value(dev, "addr_assign_type", &s);
|
r = sd_device_get_sysattr_value(dev, "addr_assign_type", &s);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
i = strtoul(s, NULL, 0);
|
r = safe_atolu(s, &i);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -868,7 +881,9 @@ static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
i = strtoul(s, NULL, 0);
|
r = safe_atolu_full(s, 10, &i);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case ARPHRD_ETHER:
|
case ARPHRD_ETHER:
|
||||||
prefix = "en";
|
prefix = "en";
|
||||||
|
|||||||
@ -11,12 +11,12 @@
|
|||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "dirent-util.h"
|
#include "dirent-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
|
#include "parse-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "sysexits.h"
|
#include "sysexits.h"
|
||||||
@ -66,7 +66,9 @@ static int format_lun_number(sd_device *dev, char **path) {
|
|||||||
if (!sysnum)
|
if (!sysnum)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
lun = strtoul(sysnum, NULL, 10);
|
r = safe_atolu_full(sysnum, 10, &lun);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
if (lun < 256)
|
if (lun < 256)
|
||||||
/* address method 0, peripheral device addressing with bus id of zero */
|
/* address method 0, peripheral device addressing with bus id of zero */
|
||||||
path_prepend(path, "lun-%lu", lun);
|
path_prepend(path, "lun-%lu", lun);
|
||||||
@ -344,8 +346,7 @@ static sd_device *handle_scsi_default(sd_device *parent, char **path) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
FOREACH_DIRENT_ALL(dent, dir, break) {
|
FOREACH_DIRENT_ALL(dent, dir, break) {
|
||||||
char *rest;
|
unsigned i;
|
||||||
int i;
|
|
||||||
|
|
||||||
if (dent->d_name[0] == '.')
|
if (dent->d_name[0] == '.')
|
||||||
continue;
|
continue;
|
||||||
@ -353,15 +354,14 @@ static sd_device *handle_scsi_default(sd_device *parent, char **path) {
|
|||||||
continue;
|
continue;
|
||||||
if (!startswith(dent->d_name, "host"))
|
if (!startswith(dent->d_name, "host"))
|
||||||
continue;
|
continue;
|
||||||
i = strtoul(&dent->d_name[4], &rest, 10);
|
if (safe_atou_full(&dent->d_name[4], 10, &i) < 0)
|
||||||
if (rest[0] != '\0')
|
|
||||||
continue;
|
continue;
|
||||||
/*
|
/*
|
||||||
* find the smallest number; the host really needs to export its
|
* find the smallest number; the host really needs to export its
|
||||||
* own instance number per parent device; relying on the global host
|
* own instance number per parent device; relying on the global host
|
||||||
* enumeration and plainly rebasing the numbers sounds unreliable
|
* enumeration and plainly rebasing the numbers sounds unreliable
|
||||||
*/
|
*/
|
||||||
if (basenum == -1 || i < basenum)
|
if (basenum == -1 || (int) i < basenum)
|
||||||
basenum = i;
|
basenum = i;
|
||||||
}
|
}
|
||||||
if (basenum == -1)
|
if (basenum == -1)
|
||||||
|
|||||||
@ -11,13 +11,13 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "device-nodes.h"
|
#include "device-nodes.h"
|
||||||
#include "device-util.h"
|
#include "device-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
|
#include "parse-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strxcpyx.h"
|
#include "strxcpyx.h"
|
||||||
#include "udev-builtin.h"
|
#include "udev-builtin.h"
|
||||||
@ -75,11 +75,9 @@ static void set_usb_iftype(char *to, int if_class_num, size_t len) {
|
|||||||
|
|
||||||
static int set_usb_mass_storage_ifsubtype(char *to, const char *from, size_t len) {
|
static int set_usb_mass_storage_ifsubtype(char *to, const char *from, size_t len) {
|
||||||
int type_num = 0;
|
int type_num = 0;
|
||||||
char *eptr;
|
|
||||||
const char *type = "generic";
|
const char *type = "generic";
|
||||||
|
|
||||||
type_num = strtoul(from, &eptr, 0);
|
if (safe_atoi(from, &type_num) >= 0) {
|
||||||
if (eptr != from) {
|
|
||||||
switch (type_num) {
|
switch (type_num) {
|
||||||
case 1: /* RBC devices */
|
case 1: /* RBC devices */
|
||||||
type = "rbc";
|
type = "rbc";
|
||||||
@ -105,12 +103,10 @@ static int set_usb_mass_storage_ifsubtype(char *to, const char *from, size_t len
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void set_scsi_type(char *to, const char *from, size_t len) {
|
static void set_scsi_type(char *to, const char *from, size_t len) {
|
||||||
int type_num;
|
unsigned type_num;
|
||||||
char *eptr;
|
|
||||||
const char *type = "generic";
|
const char *type = "generic";
|
||||||
|
|
||||||
type_num = strtoul(from, &eptr, 0);
|
if (safe_atou(from, &type_num) >= 0) {
|
||||||
if (eptr != from) {
|
|
||||||
switch (type_num) {
|
switch (type_num) {
|
||||||
case 0:
|
case 0:
|
||||||
case 0xe:
|
case 0xe:
|
||||||
@ -246,7 +242,7 @@ static int builtin_usb_id(sd_device *dev, int argc, char *argv[], bool test) {
|
|||||||
|
|
||||||
sd_device *dev_interface, *dev_usb;
|
sd_device *dev_interface, *dev_usb;
|
||||||
const char *if_class, *if_subclass;
|
const char *if_class, *if_subclass;
|
||||||
int if_class_num;
|
unsigned if_class_num;
|
||||||
int protocol = 0;
|
int protocol = 0;
|
||||||
size_t l;
|
size_t l;
|
||||||
char *s;
|
char *s;
|
||||||
@ -286,7 +282,9 @@ static int builtin_usb_id(sd_device *dev, int argc, char *argv[], bool test) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_device_debug_errno(dev_interface, r, "Failed to get bInterfaceClass attribute: %m");
|
return log_device_debug_errno(dev_interface, r, "Failed to get bInterfaceClass attribute: %m");
|
||||||
|
|
||||||
if_class_num = strtoul(if_class, NULL, 16);
|
r = safe_atou_full(if_class, 16, &if_class_num);
|
||||||
|
if (r < 0)
|
||||||
|
return log_device_debug_errno(dev_interface, r, "Failed to parse if_class: %m");
|
||||||
if (if_class_num == 8) {
|
if (if_class_num == 8) {
|
||||||
/* mass storage */
|
/* mass storage */
|
||||||
if (sd_device_get_sysattr_value(dev_interface, "bInterfaceSubClass", &if_subclass) >= 0)
|
if (sd_device_get_sysattr_value(dev_interface, "bInterfaceSubClass", &if_subclass) >= 0)
|
||||||
|
|||||||
@ -9,18 +9,6 @@ TEST_REQUIRE_INSTALL_TESTS=0
|
|||||||
# shellcheck source=test/test-functions
|
# shellcheck source=test/test-functions
|
||||||
. "${TEST_BASE_DIR:?}/test-functions"
|
. "${TEST_BASE_DIR:?}/test-functions"
|
||||||
|
|
||||||
# Explicitly override the default test_create_image() function to avoid the
|
|
||||||
# call to mask_supporting_services(), since we want to run them in TEST-01-BASIC
|
|
||||||
test_create_image() {
|
|
||||||
create_empty_image_rootdir
|
|
||||||
|
|
||||||
# Create what will eventually be our root filesystem onto an overlay
|
|
||||||
(
|
|
||||||
LOG_LEVEL=5
|
|
||||||
setup_basic_environment
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
test_append_files() {
|
test_append_files() {
|
||||||
# install tests manually so the test is functional even when -Dinstall-tests=false
|
# install tests manually so the test is functional even when -Dinstall-tests=false
|
||||||
local dst="${1:?}/usr/lib/systemd/tests/testdata/units/"
|
local dst="${1:?}/usr/lib/systemd/tests/testdata/units/"
|
||||||
|
|||||||
@ -2416,7 +2416,6 @@ test_create_image() {
|
|||||||
(
|
(
|
||||||
LOG_LEVEL=5
|
LOG_LEVEL=5
|
||||||
setup_basic_environment
|
setup_basic_environment
|
||||||
mask_supporting_services
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2467,6 +2466,13 @@ test_setup() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
mount_initdir
|
mount_initdir
|
||||||
|
# We want to test all services in TEST-01-BASIC, but mask them in
|
||||||
|
# all other tests
|
||||||
|
if [[ "${TESTID:?}" != "01" ]]; then
|
||||||
|
dinfo "Masking supporting services"
|
||||||
|
mask_supporting_services
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$hook_defined" -eq 0 ]; then
|
if [ "$hook_defined" -eq 0 ]; then
|
||||||
test_append_files "${initdir:?}"
|
test_append_files "${initdir:?}"
|
||||||
fi
|
fi
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user