summaryrefslogtreecommitdiff
path: root/src/basic
diff options
context:
space:
mode:
Diffstat (limited to 'src/basic')
-rw-r--r--src/basic/exit-status.c33
-rw-r--r--src/basic/exit-status.h14
-rw-r--r--src/basic/missing.h4
-rw-r--r--src/basic/path-util.c68
-rw-r--r--src/basic/path-util.h2
5 files changed, 94 insertions, 27 deletions
diff --git a/src/basic/exit-status.c b/src/basic/exit-status.c
index d488cfc59f..59557f8afe 100644
--- a/src/basic/exit-status.c
+++ b/src/basic/exit-status.c
@@ -24,12 +24,12 @@
#include "macro.h"
#include "set.h"
-const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) {
+const char* exit_status_to_string(int status, ExitStatusLevel level) {
/* We cast to int here, so that -Wenum doesn't complain that
* EXIT_SUCCESS/EXIT_FAILURE aren't in the enum */
- switch ((int) status) {
+ switch (status) {
case EXIT_SUCCESS:
return "SUCCESS";
@@ -39,7 +39,7 @@ const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) {
}
if (IN_SET(level, EXIT_STATUS_SYSTEMD, EXIT_STATUS_LSB)) {
- switch ((int) status) {
+ switch (status) {
case EXIT_CHDIR:
return "CHDIR";
@@ -140,19 +140,19 @@ const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) {
case EXIT_RUNTIME_DIRECTORY:
return "RUNTIME_DIRECTORY";
- case EXIT_CHOWN:
- return "CHOWN";
-
case EXIT_MAKE_STARTER:
return "MAKE_STARTER";
+ case EXIT_CHOWN:
+ return "CHOWN";
+
case EXIT_SMACK_PROCESS_LABEL:
return "SMACK_PROCESS_LABEL";
}
}
if (level == EXIT_STATUS_LSB) {
- switch ((int) status) {
+ switch (status) {
case EXIT_INVALIDARGUMENT:
return "INVALIDARGUMENT";
@@ -177,34 +177,23 @@ const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) {
return NULL;
}
-
-bool is_clean_exit(int code, int status, ExitStatusSet *success_status) {
+bool is_clean_exit(int code, int status, ExitClean clean, ExitStatusSet *success_status) {
if (code == CLD_EXITED)
return status == 0 ||
(success_status &&
set_contains(success_status->status, INT_TO_PTR(status)));
- /* If a daemon does not implement handlers for some of the
- * signals that's not considered an unclean shutdown */
+ /* If a daemon does not implement handlers for some of the signals that's not considered an unclean shutdown */
if (code == CLD_KILLED)
- return IN_SET(status, SIGHUP, SIGINT, SIGTERM, SIGPIPE) ||
+ return
+ (clean == EXIT_CLEAN_DAEMON && IN_SET(status, SIGHUP, SIGINT, SIGTERM, SIGPIPE)) ||
(success_status &&
set_contains(success_status->signal, INT_TO_PTR(status)));
return false;
}
-bool is_clean_exit_lsb(int code, int status, ExitStatusSet *success_status) {
-
- if (is_clean_exit(code, status, success_status))
- return true;
-
- return
- code == CLD_EXITED &&
- IN_SET(status, EXIT_NOTINSTALLED, EXIT_NOTCONFIGURED);
-}
-
void exit_status_set_free(ExitStatusSet *x) {
assert(x);
diff --git a/src/basic/exit-status.h b/src/basic/exit-status.h
index 2309f68815..0cfdfd7891 100644
--- a/src/basic/exit-status.h
+++ b/src/basic/exit-status.h
@@ -31,7 +31,7 @@
* https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
*/
-typedef enum ExitStatus {
+enum {
/* EXIT_SUCCESS defined by libc */
/* EXIT_FAILURE defined by libc */
EXIT_INVALIDARGUMENT = 2,
@@ -82,7 +82,7 @@ typedef enum ExitStatus {
EXIT_MAKE_STARTER,
EXIT_CHOWN,
EXIT_SMACK_PROCESS_LABEL,
-} ExitStatus;
+};
typedef enum ExitStatusLevel {
EXIT_STATUS_MINIMAL, /* only cover libc EXIT_STATUS/EXIT_FAILURE */
@@ -96,10 +96,14 @@ typedef struct ExitStatusSet {
Set *signal;
} ExitStatusSet;
-const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) _const_;
+const char* exit_status_to_string(int status, ExitStatusLevel level) _const_;
-bool is_clean_exit(int code, int status, ExitStatusSet *success_status);
-bool is_clean_exit_lsb(int code, int status, ExitStatusSet *success_status);
+typedef enum ExitClean {
+ EXIT_CLEAN_DAEMON,
+ EXIT_CLEAN_COMMAND,
+} ExitClean;
+
+bool is_clean_exit(int code, int status, ExitClean clean, ExitStatusSet *success_status);
void exit_status_set_free(ExitStatusSet *x);
bool exit_status_set_is_empty(ExitStatusSet *x);
diff --git a/src/basic/missing.h b/src/basic/missing.h
index 13ff51cd35..4a78269e33 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -1052,6 +1052,10 @@ typedef int32_t key_serial_t;
#define ETHERTYPE_LLDP 0x88cc
#endif
+#ifndef IFA_F_MCAUTOJOIN
+#define IFA_F_MCAUTOJOIN 0x400
+#endif
+
#endif
#include "missing_syscall.h"
diff --git a/src/basic/path-util.c b/src/basic/path-util.c
index b2fa81a294..c32e961af4 100644
--- a/src/basic/path-util.c
+++ b/src/basic/path-util.c
@@ -34,9 +34,11 @@
#include "alloc-util.h"
#include "extract-word.h"
#include "fs-util.h"
+#include "glob-util.h"
#include "log.h"
#include "macro.h"
#include "missing.h"
+#include "parse-util.h"
#include "path-util.h"
#include "stat-util.h"
#include "string-util.h"
@@ -814,3 +816,69 @@ bool is_device_path(const char *path) {
path_startswith(path, "/dev/") ||
path_startswith(path, "/sys/");
}
+
+int systemd_installation_has_version(const char *root, unsigned minimal_version) {
+ const char *pattern;
+ int r;
+
+ /* Try to guess if systemd installation is later than the specified version. This
+ * is hacky and likely to yield false negatives, particularly if the installation
+ * is non-standard. False positives should be relatively rare.
+ */
+
+ NULSTR_FOREACH(pattern,
+ /* /lib works for systems without usr-merge, and for systems with a sane
+ * usr-merge, where /lib is a symlink to /usr/lib. /usr/lib is necessary
+ * for Gentoo which does a merge without making /lib a symlink.
+ */
+ "lib/systemd/libsystemd-shared-*.so\0"
+ "usr/lib/systemd/libsystemd-shared-*.so\0") {
+
+ _cleanup_strv_free_ char **names = NULL;
+ _cleanup_free_ char *path = NULL;
+ char *c, **name;
+
+ path = prefix_root(root, pattern);
+ if (!path)
+ return -ENOMEM;
+
+ r = glob_extend(&names, path);
+ if (r == -ENOENT)
+ continue;
+ if (r < 0)
+ return r;
+
+ assert_se((c = endswith(path, "*.so")));
+ *c = '\0'; /* truncate the glob part */
+
+ STRV_FOREACH(name, names) {
+ /* This is most likely to run only once, hence let's not optimize anything. */
+ char *t, *t2;
+ unsigned version;
+
+ t = startswith(*name, path);
+ if (!t)
+ continue;
+
+ t2 = endswith(t, ".so");
+ if (!t2)
+ continue;
+
+ t2[0] = '\0'; /* truncate the suffix */
+
+ r = safe_atou(t, &version);
+ if (r < 0) {
+ log_debug_errno(r, "Found libsystemd shared at \"%s.so\", but failed to parse version: %m", *name);
+ continue;
+ }
+
+ log_debug("Found libsystemd shared at \"%s.so\", version %u (%s).",
+ *name, version,
+ version >= minimal_version ? "OK" : "too old");
+ if (version >= minimal_version)
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/src/basic/path-util.h b/src/basic/path-util.h
index a27c13fcc3..78472f0961 100644
--- a/src/basic/path-util.h
+++ b/src/basic/path-util.h
@@ -125,3 +125,5 @@ char *file_in_same_dir(const char *path, const char *filename);
bool hidden_or_backup_file(const char *filename) _pure_;
bool is_device_path(const char *path);
+
+int systemd_installation_has_version(const char *root, unsigned minimal_version);