mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-10-15 12:34:55 +00:00
systemd: merge branch systemd into master
Reimport systemd because it uses STRLEN() macro. We need to when building with -Wvla warning enabled. Related: https://github.com/systemd/systemd/pull/7625
This commit is contained in:
commit
e965b7679d
|
@ -1216,6 +1216,7 @@ src_libsystemd_nm_la_SOURCES = \
|
|||
src/systemd/sd-adapt/raw-clone.h \
|
||||
src/systemd/sd-adapt/sd-daemon.h \
|
||||
src/systemd/sd-adapt/stat-util.h \
|
||||
src/systemd/sd-adapt/terminal-util.h \
|
||||
src/systemd/sd-adapt/udev-util.h \
|
||||
src/systemd/sd-adapt/udev.h \
|
||||
src/systemd/sd-adapt/user-util.h \
|
||||
|
|
3
src/systemd/sd-adapt/terminal-util.h
Normal file
3
src/systemd/sd-adapt/terminal-util.h
Normal file
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
/* dummy header */
|
|
@ -22,5 +22,5 @@
|
|||
|
||||
int asynchronous_job(void* (*func)(void *p), void *arg);
|
||||
|
||||
int asynchronous_sync(void);
|
||||
int asynchronous_sync(pid_t *ret_pid);
|
||||
int asynchronous_close(int fd);
|
||||
|
|
|
@ -195,9 +195,9 @@ int fd_cloexec(int fd, bool cloexec) {
|
|||
|
||||
#if 0 /* NM_IGNORED */
|
||||
void stdio_unset_cloexec(void) {
|
||||
fd_cloexec(STDIN_FILENO, false);
|
||||
fd_cloexec(STDOUT_FILENO, false);
|
||||
fd_cloexec(STDERR_FILENO, false);
|
||||
(void) fd_cloexec(STDIN_FILENO, false);
|
||||
(void) fd_cloexec(STDOUT_FILENO, false);
|
||||
(void) fd_cloexec(STDERR_FILENO, false);
|
||||
}
|
||||
|
||||
_pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
|
||||
|
@ -230,20 +230,21 @@ int close_all_fds(const int except[], unsigned n_except) {
|
|||
|
||||
assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
|
||||
for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
|
||||
int q;
|
||||
|
||||
if (fd_in_set(fd, except, n_except))
|
||||
continue;
|
||||
|
||||
if (close_nointr(fd) < 0)
|
||||
if (errno != EBADF && r == 0)
|
||||
r = -errno;
|
||||
q = close_nointr(fd);
|
||||
if (q < 0 && q != -EBADF && r >= 0)
|
||||
r = q;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
FOREACH_DIRENT(de, d, return -errno) {
|
||||
int fd = -1;
|
||||
int fd = -1, q;
|
||||
|
||||
if (safe_atoi(de->d_name, &fd) < 0)
|
||||
/* Let's better ignore this, just in case */
|
||||
|
@ -258,11 +259,9 @@ int close_all_fds(const int except[], unsigned n_except) {
|
|||
if (fd_in_set(fd, except, n_except))
|
||||
continue;
|
||||
|
||||
if (close_nointr(fd) < 0) {
|
||||
/* Valgrind has its own FD and doesn't want to have it closed */
|
||||
if (errno != EBADF && r == 0)
|
||||
r = -errno;
|
||||
}
|
||||
q = close_nointr(fd);
|
||||
if (q < 0 && q != -EBADF && r >= 0) /* Valgrind has its own FD and doesn't want to have it closed */
|
||||
r = q;
|
||||
}
|
||||
|
||||
return r;
|
||||
|
@ -432,7 +431,7 @@ int move_fd(int from, int to, int cloexec) {
|
|||
|
||||
int acquire_data_fd(const void *data, size_t size, unsigned flags) {
|
||||
|
||||
char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
|
||||
char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
|
||||
_cleanup_close_pair_ int pipefds[2] = { -1, -1 };
|
||||
char pattern[] = "/dev/shm/data-fd-XXXXXX";
|
||||
_cleanup_close_ int fd = -1;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
|
@ -67,9 +68,15 @@ int write_string_stream_ts(
|
|||
assert(f);
|
||||
assert(line);
|
||||
|
||||
fputs(line, f);
|
||||
if (ferror(f))
|
||||
return -EIO;
|
||||
|
||||
if (fputs(line, f) == EOF)
|
||||
return -errno;
|
||||
|
||||
if (!(flags & WRITE_STRING_FILE_AVOID_NEWLINE) && !endswith(line, "\n"))
|
||||
fputc('\n', f);
|
||||
if (fputc('\n', f) == EOF)
|
||||
return -errno;
|
||||
|
||||
if (ts) {
|
||||
struct timespec twice[2] = {*ts, *ts};
|
||||
|
@ -101,6 +108,7 @@ static int write_string_file_atomic(
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
(void) fchmod_umask(fileno(f), 0644);
|
||||
|
||||
r = write_string_stream_ts(f, line, flags, ts);
|
||||
|
@ -170,6 +178,8 @@ int write_string_file_ts(
|
|||
}
|
||||
}
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
if (flags & WRITE_STRING_FILE_DISABLE_BUFFER)
|
||||
setvbuf(f, NULL, _IONBF, 0);
|
||||
|
||||
|
@ -206,10 +216,11 @@ int read_one_line_file(const char *fn, char **line) {
|
|||
if (!f)
|
||||
return -errno;
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
r = read_line(f, LONG_LINE_MAX, line);
|
||||
return r < 0 ? r : 0;
|
||||
}
|
||||
#endif /* NM_IGNORED */
|
||||
|
||||
int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
|
@ -232,6 +243,8 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
|
|||
if (!f)
|
||||
return -errno;
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
/* We try to read one byte more than we need, so that we know whether we hit eof */
|
||||
errno = 0;
|
||||
k = fread(buf, 1, l + accept_extra_nl + 1, f);
|
||||
|
@ -247,6 +260,7 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
|
|||
|
||||
return 1;
|
||||
}
|
||||
#endif /* NM_IGNORED */
|
||||
|
||||
int read_full_stream(FILE *f, char **contents, size_t *size) {
|
||||
size_t n, l;
|
||||
|
@ -327,6 +341,8 @@ int read_full_file(const char *fn, char **contents, size_t *size) {
|
|||
if (!f)
|
||||
return -errno;
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
return read_full_stream(f, contents, size);
|
||||
}
|
||||
|
||||
|
@ -884,7 +900,8 @@ int write_env_file(const char *fname, char **l) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
fchmod_umask(fileno(f), 0644);
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
(void) fchmod_umask(fileno(f), 0644);
|
||||
|
||||
STRV_FOREACH(i, l)
|
||||
write_env_var(f, *i);
|
||||
|
@ -1472,7 +1489,7 @@ int link_tmpfile(int fd, const char *path, const char *target) {
|
|||
if (rename_noreplace(AT_FDCWD, path, AT_FDCWD, target) < 0)
|
||||
return -errno;
|
||||
} else {
|
||||
char proc_fd_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
|
||||
char proc_fd_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
|
||||
|
||||
xsprintf(proc_fd_path, "/proc/self/fd/%i", fd);
|
||||
|
||||
|
|
|
@ -587,7 +587,7 @@ int tmp_dir(const char **ret) {
|
|||
}
|
||||
|
||||
int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
|
||||
char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
|
||||
char path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
|
||||
int r;
|
||||
|
||||
/* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
|
||||
|
@ -832,7 +832,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
|
|||
}
|
||||
|
||||
int access_fd(int fd, int mode) {
|
||||
char p[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
|
||||
char p[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
|
||||
int r;
|
||||
|
||||
/* Like access() but operates on an already open fd */
|
||||
|
|
|
@ -341,3 +341,5 @@ int log_syntax_internal(
|
|||
"String is not UTF-8 clean, ignoring assignment: %s", strna(_p)); \
|
||||
} \
|
||||
})
|
||||
|
||||
#define DEBUG_LOGGING _unlikely_(log_get_max_level() >= LOG_DEBUG)
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
|
@ -59,6 +60,7 @@
|
|||
#include "stat-util.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "terminal-util.h"
|
||||
#include "user-util.h"
|
||||
#include "util.h"
|
||||
|
||||
|
@ -135,6 +137,8 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
|
|||
return -errno;
|
||||
}
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
if (max_length == 1) {
|
||||
|
||||
/* If there's only room for one byte, return the empty string */
|
||||
|
@ -298,10 +302,17 @@ int rename_process(const char name[]) {
|
|||
if (isempty(name))
|
||||
return -EINVAL; /* let's not confuse users unnecessarily with an empty name */
|
||||
|
||||
if (!is_main_thread())
|
||||
return -EPERM; /* Let's not allow setting the process name from other threads than the main one, as we
|
||||
* cache things without locking, and we make assumptions that PR_SET_NAME sets the
|
||||
* process name that isn't correct on any other threads */
|
||||
|
||||
l = strlen(name);
|
||||
|
||||
/* First step, change the comm field. */
|
||||
(void) prctl(PR_SET_NAME, name);
|
||||
/* First step, change the comm field. The main thread's comm is identical to the process comm. This means we
|
||||
* can use PR_SET_NAME, which sets the thread name for the calling thread. */
|
||||
if (prctl(PR_SET_NAME, name) < 0)
|
||||
log_debug_errno(errno, "PR_SET_NAME failed: %m");
|
||||
if (l > 15) /* Linux process names can be 15 chars at max */
|
||||
truncated = true;
|
||||
|
||||
|
@ -411,6 +422,8 @@ int is_kernel_thread(pid_t pid) {
|
|||
return -errno;
|
||||
}
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
count = fread(&c, 1, 1, f);
|
||||
eof = feof(f);
|
||||
fclose(f);
|
||||
|
@ -492,6 +505,8 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
|
|||
return -errno;
|
||||
}
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
FOREACH_LINE(line, f, return -errno) {
|
||||
char *l;
|
||||
|
||||
|
@ -570,6 +585,8 @@ int get_process_environ(pid_t pid, char **env) {
|
|||
return -errno;
|
||||
}
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
while ((c = fgetc(f)) != EOF) {
|
||||
if (!GREEDY_REALLOC(outcome, allocated, sz + 5))
|
||||
return -ENOMEM;
|
||||
|
@ -704,6 +721,67 @@ int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_cod
|
|||
return -EPROTO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return values:
|
||||
* < 0 : wait_for_terminate_with_timeout() failed to get the state of the
|
||||
* process, the process timed out, the process was terminated by a
|
||||
* signal, or failed for an unknown reason.
|
||||
* >=0 : The process terminated normally with no failures.
|
||||
*
|
||||
* Success is indicated by a return value of zero, a timeout is indicated
|
||||
* by ETIMEDOUT, and all other child failure states are indicated by error
|
||||
* is indicated by a non-zero value.
|
||||
*/
|
||||
int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout) {
|
||||
sigset_t mask;
|
||||
int r;
|
||||
usec_t until;
|
||||
|
||||
assert_se(sigemptyset(&mask) == 0);
|
||||
assert_se(sigaddset(&mask, SIGCHLD) == 0);
|
||||
|
||||
/* Drop into a sigtimewait-based timeout. Waiting for the
|
||||
* pid to exit. */
|
||||
until = now(CLOCK_MONOTONIC) + timeout;
|
||||
for (;;) {
|
||||
usec_t n;
|
||||
siginfo_t status = {};
|
||||
struct timespec ts;
|
||||
|
||||
n = now(CLOCK_MONOTONIC);
|
||||
if (n >= until)
|
||||
break;
|
||||
|
||||
r = sigtimedwait(&mask, NULL, timespec_store(&ts, until - n)) < 0 ? -errno : 0;
|
||||
/* Assuming we woke due to the child exiting. */
|
||||
if (waitid(P_PID, pid, &status, WEXITED|WNOHANG) == 0) {
|
||||
if (status.si_pid == pid) {
|
||||
/* This is the correct child.*/
|
||||
if (status.si_code == CLD_EXITED)
|
||||
return (status.si_status == 0) ? 0 : -EPROTO;
|
||||
else
|
||||
return -EPROTO;
|
||||
}
|
||||
}
|
||||
/* Not the child, check for errors and proceed appropriately */
|
||||
if (r < 0) {
|
||||
switch (r) {
|
||||
case -EAGAIN:
|
||||
/* Timed out, child is likely hung. */
|
||||
return -ETIMEDOUT;
|
||||
case -EINTR:
|
||||
/* Received a different signal and should retry */
|
||||
continue;
|
||||
default:
|
||||
/* Return any unexpected errors */
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
void sigkill_wait(pid_t pid) {
|
||||
assert(pid > 1);
|
||||
|
||||
|
@ -754,6 +832,8 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value) {
|
|||
return -errno;
|
||||
}
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
l = strlen(field);
|
||||
r = 0;
|
||||
|
||||
|
@ -1062,6 +1142,222 @@ pid_t getpid_cached(void) {
|
|||
}
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
int must_be_root(void) {
|
||||
|
||||
if (geteuid() == 0)
|
||||
return 0;
|
||||
|
||||
log_error("Need to be root.");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
int safe_fork_full(
|
||||
const char *name,
|
||||
const int except_fds[],
|
||||
size_t n_except_fds,
|
||||
ForkFlags flags,
|
||||
pid_t *ret_pid) {
|
||||
|
||||
pid_t original_pid, pid;
|
||||
sigset_t saved_ss;
|
||||
bool block_signals;
|
||||
int r;
|
||||
|
||||
/* A wrapper around fork(), that does a couple of important initializations in addition to mere forking. Always
|
||||
* returns the child's PID in *ret_pid. Returns == 0 in the child, and > 0 in the parent. */
|
||||
|
||||
original_pid = getpid_cached();
|
||||
|
||||
block_signals = flags & (FORK_RESET_SIGNALS|FORK_DEATHSIG);
|
||||
|
||||
if (block_signals) {
|
||||
sigset_t ss;
|
||||
|
||||
/* We temporarily block all signals, so that the new child has them blocked initially. This way, we can be sure
|
||||
* that SIGTERMs are not lost we might send to the child. */
|
||||
if (sigfillset(&ss) < 0)
|
||||
return log_debug_errno(errno, "Failed to reset signal set: %m");
|
||||
|
||||
if (sigprocmask(SIG_SETMASK, &ss, &saved_ss) < 0)
|
||||
return log_debug_errno(errno, "Failed to reset signal mask: %m");
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
r = -errno;
|
||||
|
||||
if (block_signals) /* undo what we did above */
|
||||
(void) sigprocmask(SIG_SETMASK, &saved_ss, NULL);
|
||||
|
||||
return log_debug_errno(r, "Failed to fork: %m");
|
||||
}
|
||||
if (pid > 0) {
|
||||
/* We are in the parent process */
|
||||
|
||||
if (block_signals) /* undo what we did above */
|
||||
(void) sigprocmask(SIG_SETMASK, &saved_ss, NULL);
|
||||
|
||||
log_debug("Sucessfully forked off '%s' as PID " PID_FMT ".", strna(name), pid);
|
||||
|
||||
if (ret_pid)
|
||||
*ret_pid = pid;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* We are in the child process */
|
||||
|
||||
if (flags & FORK_REOPEN_LOG) {
|
||||
/* Close the logs if requested, before we log anything. And make sure we reopen it if needed. */
|
||||
log_close();
|
||||
log_set_open_when_needed(true);
|
||||
}
|
||||
|
||||
if (name) {
|
||||
r = rename_process(name);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to rename process, ignoring: %m");
|
||||
}
|
||||
|
||||
if (flags & FORK_DEATHSIG)
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) {
|
||||
log_debug_errno(errno, "Failed to set death signal: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (flags & FORK_RESET_SIGNALS) {
|
||||
r = reset_all_signal_handlers();
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to reset signal handlers: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* This implicitly undoes the signal mask stuff we did before the fork()ing above */
|
||||
r = reset_signal_mask();
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to reset signal mask: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (block_signals) { /* undo what we did above */
|
||||
if (sigprocmask(SIG_SETMASK, &saved_ss, NULL) < 0) {
|
||||
log_debug_errno(errno, "Failed to restore signal mask: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FORK_DEATHSIG) {
|
||||
/* Let's see if the parent PID is still the one we started from? If not, then the parent
|
||||
* already died by the time we set PR_SET_PDEATHSIG, hence let's emulate the effect */
|
||||
|
||||
if (getppid() != original_pid) {
|
||||
log_debug("Parent died early, raising SIGTERM.");
|
||||
(void) raise(SIGTERM);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FORK_CLOSE_ALL_FDS) {
|
||||
/* Close the logs here in case it got reopened above, as close_all_fds() would close them for us */
|
||||
log_close();
|
||||
|
||||
r = close_all_fds(except_fds, n_except_fds);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to close all file descriptors: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* When we were asked to reopen the logs, do so again now */
|
||||
if (flags & FORK_REOPEN_LOG) {
|
||||
log_open();
|
||||
log_set_open_when_needed(false);
|
||||
}
|
||||
|
||||
if (flags & FORK_NULL_STDIO) {
|
||||
r = make_null_stdio();
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to connect stdin/stdout to /dev/null: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret_pid)
|
||||
*ret_pid = getpid_cached();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fork_agent(const char *name, const int except[], unsigned n_except, pid_t *ret_pid, const char *path, ...) {
|
||||
bool stdout_is_tty, stderr_is_tty;
|
||||
unsigned n, i;
|
||||
va_list ap;
|
||||
char **l;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
|
||||
/* Spawns a temporary TTY agent, making sure it goes away when we go away */
|
||||
|
||||
r = safe_fork_full(name, except, n_except, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS, ret_pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
return 0;
|
||||
|
||||
/* In the child: */
|
||||
|
||||
stdout_is_tty = isatty(STDOUT_FILENO);
|
||||
stderr_is_tty = isatty(STDERR_FILENO);
|
||||
|
||||
if (!stdout_is_tty || !stderr_is_tty) {
|
||||
int fd;
|
||||
|
||||
/* Detach from stdout/stderr. and reopen
|
||||
* /dev/tty for them. This is important to
|
||||
* ensure that when systemctl is started via
|
||||
* popen() or a similar call that expects to
|
||||
* read EOF we actually do generate EOF and
|
||||
* not delay this indefinitely by because we
|
||||
* keep an unused copy of stdin around. */
|
||||
fd = open("/dev/tty", O_WRONLY);
|
||||
if (fd < 0) {
|
||||
log_error_errno(errno, "Failed to open /dev/tty: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!stdout_is_tty && dup2(fd, STDOUT_FILENO) < 0) {
|
||||
log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!stderr_is_tty && dup2(fd, STDERR_FILENO) < 0) {
|
||||
log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (fd > STDERR_FILENO)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* Count arguments */
|
||||
va_start(ap, path);
|
||||
for (n = 0; va_arg(ap, char*); n++)
|
||||
;
|
||||
va_end(ap);
|
||||
|
||||
/* Allocate strv */
|
||||
l = alloca(sizeof(char *) * (n + 1));
|
||||
|
||||
/* Fill in arguments */
|
||||
va_start(ap, path);
|
||||
for (i = 0; i <= n; i++)
|
||||
l[i] = va_arg(ap, char*);
|
||||
va_end(ap);
|
||||
|
||||
execv(path, l);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static const char *const ioprio_class_table[] = {
|
||||
[IOPRIO_CLASS_NONE] = "none",
|
||||
[IOPRIO_CLASS_RT] = "realtime",
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "format-util.h"
|
||||
#include "ioprio.h"
|
||||
#include "macro.h"
|
||||
#include "time-util.h"
|
||||
|
||||
#define procfs_file_alloca(pid, field) \
|
||||
({ \
|
||||
|
@ -41,7 +42,7 @@
|
|||
if (_pid_ == 0) { \
|
||||
_r_ = ("/proc/self/" field); \
|
||||
} else { \
|
||||
_r_ = alloca(strlen("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \
|
||||
_r_ = alloca(STRLEN("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \
|
||||
sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_); \
|
||||
} \
|
||||
_r_; \
|
||||
|
@ -61,6 +62,7 @@ int get_process_ppid(pid_t pid, pid_t *ppid);
|
|||
|
||||
int wait_for_terminate(pid_t pid, siginfo_t *status);
|
||||
int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code);
|
||||
int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout);
|
||||
|
||||
void sigkill_wait(pid_t pid);
|
||||
void sigkill_waitp(pid_t *pid);
|
||||
|
@ -142,3 +144,19 @@ int ioprio_parse_priority(const char *s, int *ret);
|
|||
pid_t getpid_cached(void);
|
||||
|
||||
int must_be_root(void);
|
||||
|
||||
typedef enum ForkFlags {
|
||||
FORK_RESET_SIGNALS = 1U << 0,
|
||||
FORK_CLOSE_ALL_FDS = 1U << 1,
|
||||
FORK_DEATHSIG = 1U << 2,
|
||||
FORK_NULL_STDIO = 1U << 3,
|
||||
FORK_REOPEN_LOG = 1U << 4,
|
||||
} ForkFlags;
|
||||
|
||||
int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);
|
||||
|
||||
static inline int safe_fork(const char *name, ForkFlags flags, pid_t *ret_pid) {
|
||||
return safe_fork_full(name, NULL, 0, flags, ret_pid);
|
||||
}
|
||||
|
||||
int fork_agent(const char *name, const int except[], unsigned n_except, pid_t *pid, const char *path, ...);
|
||||
|
|
|
@ -58,6 +58,17 @@
|
|||
# define IDN_FLAGS 0
|
||||
#endif
|
||||
|
||||
static const char* const socket_address_type_table[] = {
|
||||
[SOCK_STREAM] = "Stream",
|
||||
[SOCK_DGRAM] = "Datagram",
|
||||
[SOCK_RAW] = "Raw",
|
||||
[SOCK_RDM] = "ReliableDatagram",
|
||||
[SOCK_SEQPACKET] = "SequentialPacket",
|
||||
[SOCK_DCCP] = "DatagramCongestionControl",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(socket_address_type, int);
|
||||
|
||||
int socket_address_parse(SocketAddress *a, const char *s) {
|
||||
char *e, *n;
|
||||
unsigned u;
|
||||
|
@ -125,7 +136,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
|
|||
|
||||
} else if (startswith(s, "vsock:")) {
|
||||
/* AF_VSOCK socket in vsock:cid:port notation */
|
||||
const char *cid_start = s + strlen("vsock:");
|
||||
const char *cid_start = s + STRLEN("vsock:");
|
||||
|
||||
e = strchr(cid_start, ':');
|
||||
if (!e)
|
||||
|
@ -531,22 +542,25 @@ bool socket_address_matches_fd(const SocketAddress *a, int fd) {
|
|||
return socket_address_equal(a, &b);
|
||||
}
|
||||
|
||||
int sockaddr_port(const struct sockaddr *_sa, unsigned *port) {
|
||||
int sockaddr_port(const struct sockaddr *_sa, unsigned *ret_port) {
|
||||
union sockaddr_union *sa = (union sockaddr_union*) _sa;
|
||||
|
||||
/* Note, this returns the port as 'unsigned' rather than 'uint16_t', as AF_VSOCK knows larger ports */
|
||||
|
||||
assert(sa);
|
||||
|
||||
switch (sa->sa.sa_family) {
|
||||
|
||||
case AF_INET:
|
||||
*port = be16toh(sa->in.sin_port);
|
||||
*ret_port = be16toh(sa->in.sin_port);
|
||||
return 0;
|
||||
|
||||
case AF_INET6:
|
||||
*port = be16toh(sa->in6.sin6_port);
|
||||
*ret_port = be16toh(sa->in6.sin6_port);
|
||||
return 0;
|
||||
|
||||
case AF_VSOCK:
|
||||
*port = sa->vm.svm_port;
|
||||
*ret_port = sa->vm.svm_port;
|
||||
return 0;
|
||||
|
||||
default:
|
||||
|
|
|
@ -74,6 +74,9 @@ typedef enum SocketAddressBindIPv6Only {
|
|||
|
||||
#define socket_address_family(a) ((a)->sockaddr.sa.sa_family)
|
||||
|
||||
const char* socket_address_type_to_string(int t) _const_;
|
||||
int socket_address_type_from_string(const char *s) _pure_;
|
||||
|
||||
int socket_address_parse(SocketAddress *a, const char *s);
|
||||
int socket_address_parse_and_warn(SocketAddress *a, const char *s);
|
||||
int socket_address_parse_netlink(SocketAddress *a, const char *s);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
@ -675,10 +676,10 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) {
|
|||
if (!f)
|
||||
return NULL;
|
||||
|
||||
/* Note we use the _unlocked() stdio variants on f for performance
|
||||
* reasons. It's safe to do so since we created f here and it
|
||||
* doesn't leave our scope.
|
||||
*/
|
||||
/* Note we turn off internal locking on f for performance reasons. It's safe to do so since we created f here
|
||||
* and it doesn't leave our scope. */
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
for (i = *ibuf; i < *ibuf + isz + 1; i++) {
|
||||
|
||||
|
@ -690,21 +691,21 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) {
|
|||
else if (*i == '\x1B')
|
||||
state = STATE_ESCAPE;
|
||||
else if (*i == '\t')
|
||||
fputs_unlocked(" ", f);
|
||||
fputs(" ", f);
|
||||
else
|
||||
fputc_unlocked(*i, f);
|
||||
fputc(*i, f);
|
||||
break;
|
||||
|
||||
case STATE_ESCAPE:
|
||||
if (i >= *ibuf + isz) { /* EOT */
|
||||
fputc_unlocked('\x1B', f);
|
||||
fputc('\x1B', f);
|
||||
break;
|
||||
} else if (*i == '[') {
|
||||
state = STATE_BRACKET;
|
||||
begin = i + 1;
|
||||
} else {
|
||||
fputc_unlocked('\x1B', f);
|
||||
fputc_unlocked(*i, f);
|
||||
fputc('\x1B', f);
|
||||
fputc(*i, f);
|
||||
state = STATE_OTHER;
|
||||
}
|
||||
|
||||
|
@ -714,8 +715,8 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) {
|
|||
|
||||
if (i >= *ibuf + isz || /* EOT */
|
||||
(!(*i >= '0' && *i <= '9') && !IN_SET(*i, ';', 'm'))) {
|
||||
fputc_unlocked('\x1B', f);
|
||||
fputc_unlocked('[', f);
|
||||
fputc('\x1B', f);
|
||||
fputc('[', f);
|
||||
state = STATE_OTHER;
|
||||
i = begin-1;
|
||||
} else if (*i == 'm')
|
||||
|
|
|
@ -891,8 +891,8 @@ typedef struct ParseTimestampResult {
|
|||
int parse_timestamp(const char *t, usec_t *usec) {
|
||||
char *last_space, *tz = NULL;
|
||||
ParseTimestampResult *shared, tmp;
|
||||
int r;
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
last_space = strrchr(t, ' ');
|
||||
if (last_space != NULL && timezone_is_valid(last_space + 1))
|
||||
|
@ -905,15 +905,12 @@ int parse_timestamp(const char *t, usec_t *usec) {
|
|||
if (shared == MAP_FAILED)
|
||||
return negative_errno();
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid == -1) {
|
||||
int fork_errno = errno;
|
||||
r = safe_fork("(sd-timestamp)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG, &pid);
|
||||
if (r < 0) {
|
||||
(void) munmap(shared, sizeof *shared);
|
||||
return -fork_errno;
|
||||
return r;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
if (r == 0) {
|
||||
bool with_tz = true;
|
||||
|
||||
if (setenv("TZ", tz, 1) != 0) {
|
||||
|
|
|
@ -110,7 +110,7 @@ int socket_from_display(const char *display, char **path) {
|
|||
|
||||
k = strspn(display+1, "0123456789");
|
||||
|
||||
f = new(char, strlen("/tmp/.X11-unix/X") + k + 1);
|
||||
f = new(char, STRLEN("/tmp/.X11-unix/X") + k + 1);
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -123,45 +123,6 @@ int socket_from_display(const char *display, char **path) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int block_get_whole_disk(dev_t d, dev_t *ret) {
|
||||
char p[SYS_BLOCK_PATH_MAX("/partition")];
|
||||
_cleanup_free_ char *s = NULL;
|
||||
int r;
|
||||
unsigned n, m;
|
||||
|
||||
assert(ret);
|
||||
|
||||
/* If it has a queue this is good enough for us */
|
||||
xsprintf_sys_block_path(p, "/queue", d);
|
||||
if (access(p, F_OK) >= 0) {
|
||||
*ret = d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If it is a partition find the originating device */
|
||||
xsprintf_sys_block_path(p, "/partition", d);
|
||||
if (access(p, F_OK) < 0)
|
||||
return -ENOENT;
|
||||
|
||||
/* Get parent dev_t */
|
||||
xsprintf_sys_block_path(p, "/../dev", d);
|
||||
r = read_one_line_file(p, &s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sscanf(s, "%u:%u", &m, &n);
|
||||
if (r != 2)
|
||||
return -EINVAL;
|
||||
|
||||
/* Only return this if it is really good enough for us. */
|
||||
xsprintf_sys_block_path(p, "/queue", makedev(m, n));
|
||||
if (access(p, F_OK) < 0)
|
||||
return -ENOENT;
|
||||
|
||||
*ret = makedev(m, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool kexec_loaded(void) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
|
||||
|
@ -189,112 +150,6 @@ int prot_from_flags(int flags) {
|
|||
}
|
||||
}
|
||||
|
||||
int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
|
||||
bool stdout_is_tty, stderr_is_tty;
|
||||
pid_t parent_pid, agent_pid;
|
||||
sigset_t ss, saved_ss;
|
||||
unsigned n, i;
|
||||
va_list ap;
|
||||
char **l;
|
||||
|
||||
assert(pid);
|
||||
assert(path);
|
||||
|
||||
/* Spawns a temporary TTY agent, making sure it goes away when
|
||||
* we go away */
|
||||
|
||||
parent_pid = getpid_cached();
|
||||
|
||||
/* First we temporarily block all signals, so that the new
|
||||
* child has them blocked initially. This way, we can be sure
|
||||
* that SIGTERMs are not lost we might send to the agent. */
|
||||
assert_se(sigfillset(&ss) >= 0);
|
||||
assert_se(sigprocmask(SIG_SETMASK, &ss, &saved_ss) >= 0);
|
||||
|
||||
agent_pid = fork();
|
||||
if (agent_pid < 0) {
|
||||
assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (agent_pid != 0) {
|
||||
assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
|
||||
*pid = agent_pid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* In the child:
|
||||
*
|
||||
* Make sure the agent goes away when the parent dies */
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
/* Make sure we actually can kill the agent, if we need to, in
|
||||
* case somebody invoked us from a shell script that trapped
|
||||
* SIGTERM or so... */
|
||||
(void) reset_all_signal_handlers();
|
||||
(void) reset_signal_mask();
|
||||
|
||||
/* Check whether our parent died before we were able
|
||||
* to set the death signal and unblock the signals */
|
||||
if (getppid() != parent_pid)
|
||||
_exit(EXIT_SUCCESS);
|
||||
|
||||
/* Don't leak fds to the agent */
|
||||
close_all_fds(except, n_except);
|
||||
|
||||
stdout_is_tty = isatty(STDOUT_FILENO);
|
||||
stderr_is_tty = isatty(STDERR_FILENO);
|
||||
|
||||
if (!stdout_is_tty || !stderr_is_tty) {
|
||||
int fd;
|
||||
|
||||
/* Detach from stdout/stderr. and reopen
|
||||
* /dev/tty for them. This is important to
|
||||
* ensure that when systemctl is started via
|
||||
* popen() or a similar call that expects to
|
||||
* read EOF we actually do generate EOF and
|
||||
* not delay this indefinitely by because we
|
||||
* keep an unused copy of stdin around. */
|
||||
fd = open("/dev/tty", O_WRONLY);
|
||||
if (fd < 0) {
|
||||
log_error_errno(errno, "Failed to open /dev/tty: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!stdout_is_tty && dup2(fd, STDOUT_FILENO) < 0) {
|
||||
log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!stderr_is_tty && dup2(fd, STDERR_FILENO) < 0) {
|
||||
log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (fd > STDERR_FILENO)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* Count arguments */
|
||||
va_start(ap, path);
|
||||
for (n = 0; va_arg(ap, char*); n++)
|
||||
;
|
||||
va_end(ap);
|
||||
|
||||
/* Allocate strv */
|
||||
l = alloca(sizeof(char *) * (n + 1));
|
||||
|
||||
/* Fill in arguments */
|
||||
va_start(ap, path);
|
||||
for (i = 0; i <= n; i++)
|
||||
l[i] = va_arg(ap, char*);
|
||||
va_end(ap);
|
||||
|
||||
execv(path, l);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
bool in_initrd(void) {
|
||||
struct statfs s;
|
||||
|
||||
|
@ -704,132 +559,65 @@ int version(void) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int get_block_device(const char *path, dev_t *dev) {
|
||||
struct stat st;
|
||||
struct statfs sfs;
|
||||
|
||||
assert(path);
|
||||
assert(dev);
|
||||
|
||||
/* Get's the block device directly backing a file system. If
|
||||
* the block device is encrypted, returns the device mapper
|
||||
* block device. */
|
||||
|
||||
if (lstat(path, &st))
|
||||
return -errno;
|
||||
|
||||
if (major(st.st_dev) != 0) {
|
||||
*dev = st.st_dev;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (statfs(path, &sfs) < 0)
|
||||
return -errno;
|
||||
|
||||
if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
|
||||
return btrfs_get_block_device(path, dev);
|
||||
|
||||
return 0;
|
||||
/* This is a direct translation of str_verscmp from boot.c */
|
||||
static bool is_digit(int c) {
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
int get_block_device_harder(const char *path, dev_t *dev) {
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
_cleanup_free_ char *t = NULL;
|
||||
char p[SYS_BLOCK_PATH_MAX("/slaves")];
|
||||
struct dirent *de, *found = NULL;
|
||||
const char *q;
|
||||
unsigned maj, min;
|
||||
dev_t dt;
|
||||
int r;
|
||||
static int c_order(int c) {
|
||||
if (c == 0 || is_digit(c))
|
||||
return 0;
|
||||
|
||||
assert(path);
|
||||
assert(dev);
|
||||
if ((c >= 'a') && (c <= 'z'))
|
||||
return c;
|
||||
|
||||
/* Gets the backing block device for a file system, and
|
||||
* handles LUKS encrypted file systems, looking for its
|
||||
* immediate parent, if there is one. */
|
||||
return c + 0x10000;
|
||||
}
|
||||
|
||||
r = get_block_device(path, &dt);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
int str_verscmp(const char *s1, const char *s2) {
|
||||
const char *os1, *os2;
|
||||
|
||||
xsprintf_sys_block_path(p, "/slaves", dt);
|
||||
d = opendir(p);
|
||||
if (!d) {
|
||||
if (errno == ENOENT)
|
||||
goto fallback;
|
||||
assert(s1);
|
||||
assert(s2);
|
||||
|
||||
return -errno;
|
||||
}
|
||||
os1 = s1;
|
||||
os2 = s2;
|
||||
|
||||
FOREACH_DIRENT_ALL(de, d, return -errno) {
|
||||
while (*s1 || *s2) {
|
||||
int first;
|
||||
|
||||
if (dot_or_dot_dot(de->d_name))
|
||||
continue;
|
||||
while ((*s1 && !is_digit(*s1)) || (*s2 && !is_digit(*s2))) {
|
||||
int order;
|
||||
|
||||
if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
|
||||
continue;
|
||||
|
||||
if (found) {
|
||||
_cleanup_free_ char *u = NULL, *v = NULL, *a = NULL, *b = NULL;
|
||||
|
||||
/* We found a device backed by multiple other devices. We don't really support automatic
|
||||
* discovery on such setups, with the exception of dm-verity partitions. In this case there are
|
||||
* two backing devices: the data partition and the hash partition. We are fine with such
|
||||
* setups, however, only if both partitions are on the same physical device. Hence, let's
|
||||
* verify this. */
|
||||
|
||||
u = strjoin(p, "/", de->d_name, "/../dev");
|
||||
if (!u)
|
||||
return -ENOMEM;
|
||||
|
||||
v = strjoin(p, "/", found->d_name, "/../dev");
|
||||
if (!v)
|
||||
return -ENOMEM;
|
||||
|
||||
r = read_one_line_file(u, &a);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to read %s: %m", u);
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
r = read_one_line_file(v, &b);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to read %s: %m", v);
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
/* Check if the parent device is the same. If not, then the two backing devices are on
|
||||
* different physical devices, and we don't support that. */
|
||||
if (!streq(a, b))
|
||||
goto fallback;
|
||||
order = c_order(*s1) - c_order(*s2);
|
||||
if (order != 0)
|
||||
return order;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
|
||||
found = de;
|
||||
while (*s1 == '0')
|
||||
s1++;
|
||||
while (*s2 == '0')
|
||||
s2++;
|
||||
|
||||
first = 0;
|
||||
while (is_digit(*s1) && is_digit(*s2)) {
|
||||
if (first == 0)
|
||||
first = *s1 - *s2;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
|
||||
if (is_digit(*s1))
|
||||
return 1;
|
||||
if (is_digit(*s2))
|
||||
return -1;
|
||||
|
||||
if (first != 0)
|
||||
return first;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
goto fallback;
|
||||
|
||||
q = strjoina(p, "/", found->d_name, "/dev");
|
||||
|
||||
r = read_one_line_file(q, &t);
|
||||
if (r == -ENOENT)
|
||||
goto fallback;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (sscanf(t, "%u:%u", &maj, &min) != 2)
|
||||
return -EINVAL;
|
||||
|
||||
if (maj == 0)
|
||||
goto fallback;
|
||||
|
||||
*dev = makedev(maj, min);
|
||||
return 1;
|
||||
|
||||
fallback:
|
||||
*dev = dt;
|
||||
return 1;
|
||||
return strcmp(os1, os2);
|
||||
}
|
||||
#endif /* NM_IGNORED */
|
||||
|
|
|
@ -71,8 +71,6 @@ bool plymouth_running(void);
|
|||
bool display_is_local(const char *display) _pure_;
|
||||
int socket_from_display(const char *display, char **path);
|
||||
|
||||
int block_get_whole_disk(dev_t d, dev_t *ret);
|
||||
|
||||
#define NULSTR_FOREACH(i, l) \
|
||||
for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
|
||||
|
||||
|
@ -86,8 +84,6 @@ bool kexec_loaded(void);
|
|||
|
||||
int prot_from_flags(int flags) _const_;
|
||||
|
||||
int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...);
|
||||
|
||||
bool in_initrd(void);
|
||||
void in_initrd_force(bool value);
|
||||
|
||||
|
@ -194,5 +190,4 @@ int update_reboot_parameter_and_warn(const char *param);
|
|||
|
||||
int version(void);
|
||||
|
||||
int get_block_device(const char *path, dev_t *dev);
|
||||
int get_block_device_harder(const char *path, dev_t *dev);
|
||||
int str_verscmp(const char *s1, const char *s2);
|
||||
|
|
|
@ -119,7 +119,8 @@ bool net_match_config(const struct ether_addr *match_mac,
|
|||
char * const *match_names,
|
||||
Condition *match_host,
|
||||
Condition *match_virt,
|
||||
Condition *match_kernel,
|
||||
Condition *match_kernel_cmdline,
|
||||
Condition *match_kernel_version,
|
||||
Condition *match_arch,
|
||||
const struct ether_addr *dev_mac,
|
||||
const char *dev_path,
|
||||
|
@ -134,7 +135,10 @@ bool net_match_config(const struct ether_addr *match_mac,
|
|||
if (match_virt && condition_test(match_virt) <= 0)
|
||||
return false;
|
||||
|
||||
if (match_kernel && condition_test(match_kernel) <= 0)
|
||||
if (match_kernel_cmdline && condition_test(match_kernel_cmdline) <= 0)
|
||||
return false;
|
||||
|
||||
if (match_kernel_version && condition_test(match_kernel_version) <= 0)
|
||||
return false;
|
||||
|
||||
if (match_arch && condition_test(match_arch) <= 0)
|
||||
|
|
|
@ -37,7 +37,8 @@ bool net_match_config(const struct ether_addr *match_mac,
|
|||
char * const *match_name,
|
||||
Condition *match_host,
|
||||
Condition *match_virt,
|
||||
Condition *match_kernel,
|
||||
Condition *match_kernel_cmdline,
|
||||
Condition *match_kernel_version,
|
||||
Condition *match_arch,
|
||||
const struct ether_addr *dev_mac,
|
||||
const char *dev_path,
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
@ -878,7 +879,8 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
|
|||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
fchmod(fileno(f), 0644);
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
(void) fchmod(fileno(f), 0644);
|
||||
|
||||
fprintf(f,
|
||||
"# This is private data. Do not parse.\n");
|
||||
|
@ -925,16 +927,16 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
|
|||
|
||||
r = sd_dhcp_lease_get_dns(lease, &addresses);
|
||||
if (r > 0) {
|
||||
fputs_unlocked("DNS=", f);
|
||||
fputs("DNS=", f);
|
||||
serialize_in_addrs(f, addresses, r);
|
||||
fputs_unlocked("\n", f);
|
||||
fputs("\n", f);
|
||||
}
|
||||
|
||||
r = sd_dhcp_lease_get_ntp(lease, &addresses);
|
||||
if (r > 0) {
|
||||
fputs_unlocked("NTP=", f);
|
||||
fputs("NTP=", f);
|
||||
serialize_in_addrs(f, addresses, r);
|
||||
fputs_unlocked("\n", f);
|
||||
fputs("\n", f);
|
||||
}
|
||||
|
||||
r = sd_dhcp_lease_get_domainname(lease, &string);
|
||||
|
@ -943,9 +945,9 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
|
|||
|
||||
r = sd_dhcp_lease_get_search_domains(lease, &search_domains);
|
||||
if (r > 0) {
|
||||
fputs_unlocked("DOMAIN_SEARCH_LIST=", f);
|
||||
fputs("DOMAIN_SEARCH_LIST=", f);
|
||||
fputstrv(f, search_domains, NULL, NULL);
|
||||
fputs_unlocked("\n", f);
|
||||
fputs("\n", f);
|
||||
}
|
||||
|
||||
r = sd_dhcp_lease_get_hostname(lease, &string);
|
||||
|
|
Loading…
Reference in a new issue