summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/shared/Makefile.am21
-rw-r--r--src/shared/device-nodes.c6
-rw-r--r--src/shared/fileio.c41
-rw-r--r--src/shared/fileio.h1
-rw-r--r--src/shared/label.c123
-rw-r--r--src/shared/label.h2
-rw-r--r--src/shared/log.c2
-rw-r--r--src/shared/missing.h4
-rw-r--r--src/shared/mkdir-label.c37
-rw-r--r--src/shared/mkdir.c68
-rw-r--r--src/shared/mkdir.h10
-rw-r--r--src/shared/path-util.c33
-rw-r--r--src/shared/path-util.h1
-rw-r--r--src/shared/selinux-util.c49
-rw-r--r--src/shared/selinux-util.h25
-rw-r--r--src/shared/set.h4
-rw-r--r--src/shared/smack-util.h6
-rw-r--r--src/shared/strv.h6
-rw-r--r--src/shared/utf8.c46
-rw-r--r--src/shared/utf8.h7
-rw-r--r--src/shared/util.c220
-rw-r--r--src/shared/util.h6
-rw-r--r--src/shared/virt.c224
23 files changed, 471 insertions, 471 deletions
diff --git a/src/shared/Makefile.am b/src/shared/Makefile.am
index 4c9f20697b..def06fd326 100644
--- a/src/shared/Makefile.am
+++ b/src/shared/Makefile.am
@@ -7,18 +7,20 @@ libudev_shared_la_SOURCES=\
cgroup-util.c \
conf-files.c \
device-nodes.c \
- dev-setup.c \
+ dev-setup.c \
exit-status.c \
fileio.c \
hashmap.c \
- label.c \
+ label.c \
log.c \
- mkdir.c \
+ mkdir.c \
+ mkdir-label.c \
MurmurHash2.c \
path-util.c \
+ selinux-util.c \
set.c \
siphash24.c \
- smack-util.c \
+ smack-util.c \
strbuf.c \
strv.c \
strxcpyx.c \
@@ -32,21 +34,22 @@ noinst_HEADERS = \
conf-files.h \
def.h \
device-nodes.h \
- dev-setup.h \
+ dev-setup.h \
exit-status.h \
fileio.h \
hashmap.h \
ioprio.h \
- label.h \
+ label.h \
log.h \
macro.h \
missing.h \
- mkdir.h \
+ mkdir.h \
MurmurHash2.h \
path-util.h \
+ selinux-util.h \
set.h \
siphash24.h \
- smack-util.h \
+ smack-util.h \
socket-util.h \
sparse-endian.h \
strbuf.h \
@@ -55,7 +58,7 @@ noinst_HEADERS = \
time-util.h \
util.h \
utf8.h \
- udev-util.h \
+ udev-util.h \
virt.h
libudev_shared_la_LDFLAGS = \
diff --git a/src/shared/device-nodes.c b/src/shared/device-nodes.c
index 5ddcaf042c..e235de83e1 100644
--- a/src/shared/device-nodes.c
+++ b/src/shared/device-nodes.c
@@ -21,8 +21,8 @@
#include <stdlib.h>
#include <stdio.h>
-#include <stdint.h>
#include <string.h>
+#include <stdint.h>
#include <sys/types.h>
#include "device-nodes.h"
@@ -42,7 +42,7 @@ int encode_devnode_name(const char *str, char *str_enc, size_t len) {
size_t i, j;
if (str == NULL || str_enc == NULL)
- return -1;
+ return -EINVAL;
for (i = 0, j = 0; str[i] != '\0'; i++) {
int seqlen;
@@ -71,5 +71,5 @@ int encode_devnode_name(const char *str, char *str_enc, size_t len) {
str_enc[j] = '\0';
return 0;
err:
- return -1;
+ return -EINVAL;
}
diff --git a/src/shared/fileio.c b/src/shared/fileio.c
index fe27b23001..5ea4c1913b 100644
--- a/src/shared/fileio.c
+++ b/src/shared/fileio.c
@@ -83,29 +83,33 @@ int read_one_line_file(const char *fn, char **line) {
return 0;
}
-int read_full_file(const char *fn, char **contents, size_t *size) {
- _cleanup_fclose_ FILE *f = NULL;
+int read_full_stream(FILE *f, char **contents, size_t *size) {
size_t n, l;
_cleanup_free_ char *buf = NULL;
struct stat st;
- assert(fn);
+ assert(f);
assert(contents);
- f = fopen(fn, "re");
- if (!f)
- return -errno;
-
if (fstat(fileno(f), &st) < 0)
return -errno;
- /* Safety check */
- if (st.st_size > 4*1024*1024)
- return -E2BIG;
+ n = LINE_MAX;
- n = st.st_size > 0 ? st.st_size : LINE_MAX;
- l = 0;
+ if (S_ISREG(st.st_mode)) {
+
+ /* Safety check */
+ if (st.st_size > 4*1024*1024)
+ return -E2BIG;
+
+ /* Start with the right file size, but be prepared for
+ * files from /proc which generally report a file size
+ * of 0 */
+ if (st.st_size > 0)
+ n = st.st_size;
+ }
+ l = 0;
for (;;) {
char *t;
size_t k;
@@ -141,3 +145,16 @@ int read_full_file(const char *fn, char **contents, size_t *size) {
return 0;
}
+
+int read_full_file(const char *fn, char **contents, size_t *size) {
+ _cleanup_fclose_ FILE *f = NULL;
+
+ assert(fn);
+ assert(contents);
+
+ f = fopen(fn, "re");
+ if (!f)
+ return -errno;
+
+ return read_full_stream(f, contents, size);
+}
diff --git a/src/shared/fileio.h b/src/shared/fileio.h
index 55c5d92486..d29e2dfa03 100644
--- a/src/shared/fileio.h
+++ b/src/shared/fileio.h
@@ -25,3 +25,4 @@ int write_string_stream(FILE *f, const char *line);
int write_string_file(const char *fn, const char *line);
int read_one_line_file(const char *fn, char **line);
int read_full_file(const char *fn, char **contents, size_t *size);
+int read_full_stream(FILE *f, char **contents, size_t *size);
diff --git a/src/shared/label.c b/src/shared/label.c
index dca2a21228..eb95c31692 100644
--- a/src/shared/label.c
+++ b/src/shared/label.c
@@ -28,23 +28,54 @@
#include "label.h"
#include "util.h"
#include "path-util.h"
+#include "selinux-util.h"
+#include "smack-util.h"
#ifdef HAVE_SELINUX
-#include <stdbool.h>
-#include <selinux/selinux.h>
-#include <selinux/label.h>
-
static struct selabel_handle *label_hnd = NULL;
-static int use_selinux_cached = -1;
+#endif
-bool use_selinux(void) {
- if (use_selinux_cached < 0)
- use_selinux_cached = is_selinux_enabled() > 0;
+static int smack_relabel_in_dev(const char *path) {
+ int r = 0;
- return use_selinux_cached;
-}
+#ifdef HAVE_SMACK
+ struct stat sb;
+ const char *label;
+
+ /*
+ * Path must be in /dev and must exist
+ */
+ if (!path_startswith(path, "/dev"))
+ return 0;
+
+ r = lstat(path, &sb);
+ if (r < 0)
+ return -errno;
+
+ /*
+ * Label directories and character devices "*".
+ * Label symlinks "_".
+ * Don't change anything else.
+ */
+ if (S_ISDIR(sb.st_mode))
+ label = SMACK_STAR_LABEL;
+ else if (S_ISLNK(sb.st_mode))
+ label = SMACK_FLOOR_LABEL;
+ else if (S_ISCHR(sb.st_mode))
+ label = SMACK_STAR_LABEL;
+ else
+ return 0;
+
+ r = setxattr(path, "security.SMACK64", label, strlen(label), 0);
+ if (r < 0) {
+ log_error("Smack relabeling \"%s\" %m", path);
+ return -errno;
+ }
#endif
+ return r;
+}
+
int label_init(const char *prefix) {
int r = 0;
@@ -92,14 +123,14 @@ int label_init(const char *prefix) {
return r;
}
-int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
+static int label_fix_selinux(const char *path, bool ignore_enoent, bool ignore_erofs) {
int r = 0;
#ifdef HAVE_SELINUX
struct stat st;
security_context_t fcon;
- if (!use_selinux() || !label_hnd)
+ if (!label_hnd)
return 0;
r = lstat(path, &st);
@@ -122,6 +153,7 @@ int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
if (r < 0) {
/* Ignore ENOENT in some cases */
+
if (ignore_enoent && errno == ENOENT)
return 0;
@@ -137,10 +169,31 @@ int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
return r;
}
+int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
+ int r = 0;
+
+ if (use_selinux()) {
+ r = label_fix_selinux(path, ignore_enoent, ignore_erofs);
+ if (r < 0)
+ return r;
+ }
+
+ if (use_smack()) {
+ r = smack_relabel_in_dev(path);
+ if (r < 0)
+ return r;
+ }
+
+ return r;
+}
+
void label_finish(void) {
#ifdef HAVE_SELINUX
- if (use_selinux() && label_hnd)
+ if (!use_selinux())
+ return;
+
+ if (label_hnd)
selabel_close(label_hnd);
#endif
}
@@ -177,6 +230,8 @@ int label_context_set(const char *path, mode_t mode) {
void label_context_clear(void) {
#ifdef HAVE_SELINUX
+ PROTECT_ERRNO;
+
if (!use_selinux())
return;
@@ -184,27 +239,26 @@ void label_context_clear(void) {
#endif
}
-int label_mkdir(const char *path, mode_t mode, bool apply) {
+static int label_mkdir_selinux(const char *path, mode_t mode) {
+ int r = 0;
- /* Creates a directory and labels it according to the SELinux policy */
#ifdef HAVE_SELINUX
- int r;
+ /* Creates a directory and labels it according to the SELinux policy */
security_context_t fcon = NULL;
- if (!apply || !use_selinux() || !label_hnd)
- goto skipped;
+ if (!label_hnd)
+ return 0;
if (path_is_absolute(path))
r = selabel_lookup_raw(label_hnd, &fcon, path, S_IFDIR);
else {
- char *newpath;
+ _cleanup_free_ char *newpath;
newpath = path_make_absolute_cwd(path);
if (!newpath)
return -ENOMEM;
r = selabel_lookup_raw(label_hnd, &fcon, newpath, S_IFDIR);
- free(newpath);
}
if (r == 0)
@@ -226,12 +280,35 @@ int label_mkdir(const char *path, mode_t mode, bool apply) {
finish:
setfscreatecon(NULL);
freecon(fcon);
+#endif
return r;
+}
-skipped:
-#endif
- return mkdir(path, mode) < 0 ? -errno : 0;
+int label_mkdir(const char *path, mode_t mode) {
+ int r;
+
+ if (use_selinux()) {
+ r = label_mkdir_selinux(path, mode);
+ if (r < 0)
+ return r;
+ }
+
+ if (use_smack()) {
+ r = mkdir(path, mode);
+ if (r < 0 && errno != EEXIST)
+ return -errno;
+
+ r = smack_relabel_in_dev(path);
+ if (r < 0)
+ return r;
+ }
+
+ r = mkdir(path, mode);
+ if (r < 0 && errno != EEXIST)
+ return -errno;
+
+ return 0;
}
int label_apply(const char *path, const char *label) {
diff --git a/src/shared/label.h b/src/shared/label.h
index a8dbcdc8b7..ec64fa6816 100644
--- a/src/shared/label.h
+++ b/src/shared/label.h
@@ -33,6 +33,6 @@ int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs);
int label_context_set(const char *path, mode_t mode);
void label_context_clear(void);
-int label_mkdir(const char *path, mode_t mode, bool apply);
+int label_mkdir(const char *path, mode_t mode);
int label_apply(const char *path, const char *label);
diff --git a/src/shared/log.c b/src/shared/log.c
index 0237d20ff2..56aa4e14d4 100644
--- a/src/shared/log.c
+++ b/src/shared/log.c
@@ -30,11 +30,11 @@
#include <string.h>
#include "log.h"
-#include "time-util.h"
#include "util.h"
#include "missing.h"
#include "macro.h"
#include "socket-util.h"
+#include "time-util.h"
#define SNDBUF_SIZE (8*1024*1024)
diff --git a/src/shared/missing.h b/src/shared/missing.h
index 3c758956c6..2cb12786b7 100644
--- a/src/shared/missing.h
+++ b/src/shared/missing.h
@@ -78,10 +78,6 @@ static inline pid_t gettid(void) {
}
#endif
-#ifndef MS_PRIVATE
-#define MS_PRIVATE (1 << 18)
-#endif
-
#ifndef MS_REC
#define MS_REC 16384
#endif
diff --git a/src/shared/mkdir-label.c b/src/shared/mkdir-label.c
new file mode 100644
index 0000000000..073ecab7b9
--- /dev/null
+++ b/src/shared/mkdir-label.c
@@ -0,0 +1,37 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+ Copyright 2013 Kay Sievers
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <assert.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "label.h"
+#include "util.h"
+#include "path-util.h"
+#include "mkdir.h"
+
+int mkdir_parents_label(const char *path, mode_t mode) {
+ return mkdir_parents_internal(NULL, path, mode, label_mkdir);
+}
diff --git a/src/shared/mkdir.c b/src/shared/mkdir.c
index 770ee994c4..874433dc90 100644
--- a/src/shared/mkdir.c
+++ b/src/shared/mkdir.c
@@ -29,52 +29,24 @@
#include "label.h"
#include "util.h"
+#include "path-util.h"
#include "mkdir.h"
-static int is_dir(const char* path) {
+int is_dir(const char* path, bool follow) {
struct stat st;
- if (stat(path, &st) < 0)
- return -errno;
+ if (follow) {
+ if (stat(path, &st) < 0)
+ return -errno;
+ } else {
+ if (lstat(path, &st) < 0)
+ return -errno;
+ }
return S_ISDIR(st.st_mode);
}
-
-char* path_startswith(const char *path, const char *prefix) {
- assert(path);
- assert(prefix);
-
- if ((path[0] == '/') != (prefix[0] == '/'))
- return NULL;
-
- for (;;) {
- size_t a, b;
-
- path += strspn(path, "/");
- prefix += strspn(prefix, "/");
-
- if (*prefix == 0)
- return (char*) path;
-
- if (*path == 0)
- return NULL;
-
- a = strcspn(path, "/");
- b = strcspn(prefix, "/");
-
- if (a != b)
- return NULL;
-
- if (memcmp(path, prefix, a) != 0)
- return NULL;
-
- path += a;
- prefix += b;
- }
-}
-
-static int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, bool apply) {
+int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) {
const char *p, *e;
int r;
@@ -97,7 +69,7 @@ static int mkdir_parents_internal(const char *prefix, const char *path, mode_t m
memcpy(buf, path, e-path);
buf[e-path] = 0;
- r = is_dir(p);
+ r = is_dir(p, true);
if (r > 0)
return 0;
if (r == 0)
@@ -122,36 +94,32 @@ static int mkdir_parents_internal(const char *prefix, const char *path, mode_t m
if (prefix && path_startswith(prefix, t))
continue;
- r = label_mkdir(t, mode, apply);
+ r = _mkdir(t, mode);
if (r < 0 && errno != EEXIST)
return -errno;
}
}
int mkdir_parents(const char *path, mode_t mode) {
- return mkdir_parents_internal(NULL, path, mode, false);
-}
-
-int mkdir_parents_label(const char *path, mode_t mode) {
- return mkdir_parents_internal(NULL, path, mode, true);
+ return mkdir_parents_internal(NULL, path, mode, mkdir);
}
-static int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, bool apply) {
+int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) {
int r;
/* Like mkdir -p */
- r = mkdir_parents_internal(prefix, path, mode, apply);
+ r = mkdir_parents_internal(prefix, path, mode, _mkdir);
if (r < 0)
return r;
- r = label_mkdir(path, mode, apply);
- if (r < 0 && (errno != EEXIST || is_dir(path) <= 0))
+ r = _mkdir(path, mode);
+ if (r < 0 && (errno != EEXIST || is_dir(path, true) <= 0))
return -errno;
return 0;
}
int mkdir_p(const char *path, mode_t mode) {
- return mkdir_p_internal(NULL, path, mode, false);
+ return mkdir_p_internal(NULL, path, mode, mkdir);
}
diff --git a/src/shared/mkdir.h b/src/shared/mkdir.h
index 24ffa6364c..399f2c0ff6 100644
--- a/src/shared/mkdir.h
+++ b/src/shared/mkdir.h
@@ -1,7 +1,6 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-#ifndef foomkdirhfoo
-#define foomkdirhfoo
+#pragma once
/***
This file is part of systemd.
@@ -22,8 +21,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-char* path_startswith(const char *path, const char *prefix) _pure_;
int mkdir_parents(const char *path, mode_t mode);
-int mkdir_parents_label(const char *path, mode_t mode);
int mkdir_p(const char *path, mode_t mode);
-#endif
+
+/* internally used */
+typedef int (*mkdir_func_t)(const char *pathname, mode_t mode);
+int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir);
diff --git a/src/shared/path-util.c b/src/shared/path-util.c
index 783d130842..2a2f33dbca 100644
--- a/src/shared/path-util.c
+++ b/src/shared/path-util.c
@@ -248,6 +248,39 @@ char *path_kill_slashes(char *path) {
return path;
}
+char* path_startswith(const char *path, const char *prefix) {
+ assert(path);
+ assert(prefix);
+
+ if ((path[0] == '/') != (prefix[0] == '/'))
+ return NULL;
+
+ for (;;) {
+ size_t a, b;
+
+ path += strspn(path, "/");
+ prefix += strspn(prefix, "/");
+
+ if (*prefix == 0)
+ return (char*) path;
+
+ if (*path == 0)
+ return NULL;
+
+ a = strcspn(path, "/");
+ b = strcspn(prefix, "/");
+
+ if (a != b)
+ return NULL;
+
+ if (memcmp(path, prefix, a) != 0)
+ return NULL;
+
+ path += a;
+ prefix += b;
+ }
+}
+
bool path_equal(const char *a, const char *b) {
assert(a);
assert(b);
diff --git a/src/shared/path-util.h b/src/shared/path-util.h
index a62624c1b3..e0cab15a3e 100644
--- a/src/shared/path-util.h
+++ b/src/shared/path-util.h
@@ -27,6 +27,7 @@ bool path_is_absolute(const char *p) _pure_;
char* path_make_absolute(const char *p, const char *prefix);
char* path_make_absolute_cwd(const char *p);
char* path_kill_slashes(char *path);
+char* path_startswith(const char *path, const char *prefix) _pure_;
bool path_equal(const char *a, const char *b) _pure_;
char** path_strv_resolve(char **l, const char *prefix);
diff --git a/src/shared/selinux-util.c b/src/shared/selinux-util.c
new file mode 100644
index 0000000000..16c74a4ac0
--- /dev/null
+++ b/src/shared/selinux-util.c
@@ -0,0 +1,49 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "selinux-util.h"
+
+#ifdef HAVE_SELINUX
+
+#include <selinux/selinux.h>
+
+static int use_selinux_cached = -1;
+
+bool use_selinux(void) {
+
+ if (use_selinux_cached < 0)
+ use_selinux_cached = is_selinux_enabled() > 0;
+
+ return use_selinux_cached;
+}
+
+void retest_selinux(void) {
+ use_selinux_cached = -1;
+}
+
+#else
+
+bool use_selinux(void) {
+ return false;
+}
+
+void retest_selinux(void) {
+}
+
+#endif
diff --git a/src/shared/selinux-util.h b/src/shared/selinux-util.h
new file mode 100644
index 0000000000..b5b8faa06a
--- /dev/null
+++ b/src/shared/selinux-util.h
@@ -0,0 +1,25 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#pragma once
+
+#include <stdbool.h>
+
+bool use_selinux(void);
+void retest_selinux(void);
diff --git a/src/shared/set.h b/src/shared/set.h
index c6455be7c1..dd4d458792 100644
--- a/src/shared/set.h
+++ b/src/shared/set.h
@@ -34,9 +34,6 @@ typedef struct Set Set;
Set *set_new(hash_func_t hash_func, compare_func_t compare_func);
void set_free(Set* s);
-static inline void set_freep(Set **s) {
- set_free(*s);
-}
int set_put(Set *s, void *value);
void *set_get(Set *s, void *value);
@@ -45,4 +42,5 @@ bool set_contains(Set *s, void *value);
void *set_iterate(Set *s, Iterator *i);
void *set_iterate_backwards(Set *s, Iterator *i);
+DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free);
#define _cleanup_set_free_ _cleanup_(set_freep)
diff --git a/src/shared/smack-util.h b/src/shared/smack-util.h
index 88704894e7..5e555def2b 100644
--- a/src/shared/smack-util.h
+++ b/src/shared/smack-util.h
@@ -19,9 +19,15 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#pragma once
+
#include <stdbool.h>
+#define SMACK_FLOOR_LABEL "_"
+#define SMACK_STAR_LABEL "*"
+
bool use_smack(void);
+
int smack_label_path(const char *path, const char *label);
int smack_label_fd(int fd, const char *label);
int smack_label_ip_in_fd(int fd, const char *label);
diff --git a/src/shared/strv.h b/src/shared/strv.h
index 4cc918367e..98e339c02f 100644
--- a/src/shared/strv.h
+++ b/src/shared/strv.h
@@ -27,11 +27,7 @@
#include "macro.h"
void strv_free(char **l);
-static inline void strv_freep(char ***l) {
- strv_free(*l);
-}
-
-void strv_free(char **l);
+DEFINE_TRIVIAL_CLEANUP_FUNC(char**, strv_free);
#define _cleanup_strv_free_ _cleanup_(strv_freep)
char **strv_copy(char * const *l);
diff --git a/src/shared/utf8.c b/src/shared/utf8.c
index 1044fb6489..403166d7f9 100644
--- a/src/shared/utf8.c
+++ b/src/shared/utf8.c
@@ -78,8 +78,11 @@ static bool is_unicode_control(uint32_t ch) {
/* count of characters used to encode one unicode char */
static int utf8_encoded_expected_len(const char *str) {
- unsigned char c = (unsigned char)str[0];
+ unsigned char c;
+ assert(str);
+
+ c = (unsigned char) str[0];
if (c < 0x80)
return 1;
if ((c & 0xe0) == 0xc0)
@@ -92,16 +95,18 @@ static int utf8_encoded_expected_len(const char *str) {
return 5;
if ((c & 0xfe) == 0xfc)
return 6;
+
return 0;
}
/* decode one unicode char */
int utf8_encoded_to_unichar(const char *str) {
- int unichar;
- int len;
- int i;
+ int unichar, len, i;
+
+ assert(str);
len = utf8_encoded_expected_len(str);
+
switch (len) {
case 1:
return (int)str[0];
@@ -121,12 +126,12 @@ int utf8_encoded_to_unichar(const char *str) {
unichar = (int)str[0] & 0x01;
break;
default:
- return -1;
+ return -EINVAL;
}
for (i = 1; i < len; i++) {
if (((int)str[i] & 0xc0) != 0x80)
- return -1;
+ return -EINVAL;
unichar <<= 6;
unichar |= (int)str[i] & 0x3f;
}
@@ -134,16 +139,21 @@ int utf8_encoded_to_unichar(const char *str) {
return unichar;
}
-bool utf8_is_printable(const char* str, size_t length) {
+bool utf8_is_printable_newline(const char* str, size_t length, bool newline) {
const uint8_t *p;
assert(str);
for (p = (const uint8_t*) str; length;) {
- int encoded_len = utf8_encoded_valid_unichar((const char *)p);
- int val = utf8_encoded_to_unichar((const char*)p);
+ int encoded_len, val;
- if (encoded_len < 0 || val < 0 || is_unicode_control(val))
+ encoded_len = utf8_encoded_valid_unichar((const char *) p);
+ val = utf8_encoded_to_unichar((const char*) p);
+
+ if (encoded_len < 0 ||
+ val < 0 ||
+ is_unicode_control(val) ||
+ (!newline && val == '\n'))
return false;
length -= encoded_len;
@@ -203,6 +213,7 @@ char *utf16_to_utf8(const void *s, size_t length) {
/* expected size used to encode one unicode char */
static int utf8_unichar_to_encoded_len(int unichar) {
+
if (unichar < 0x80)
return 1;
if (unichar < 0x800)
@@ -213,18 +224,19 @@ static int utf8_unichar_to_encoded_len(int unichar) {
return 4;
if (unichar < 0x4000000)
return 5;
+
return 6;
}
/* validate one encoded unicode char and return its length */
int utf8_encoded_valid_unichar(const char *str) {
- int len;
- int unichar;
- int i;
+ int len, unichar, i;
+
+ assert(str);
len = utf8_encoded_expected_len(str);
if (len == 0)
- return -1;
+ return -EINVAL;
/* ascii is valid */
if (len == 1)
@@ -233,17 +245,17 @@ int utf8_encoded_valid_unichar(const char *str) {
/* check if expected encoded chars are available */
for (i = 0; i < len; i++)
if ((str[i] & 0x80) != 0x80)
- return -1;
+ return -EINVAL;
unichar = utf8_encoded_to_unichar(str);
/* check if encoded length matches encoded value */
if (utf8_unichar_to_encoded_len(unichar) != len)
- return -1;
+ return -EINVAL;
/* check if value has valid range */
if (!is_unicode_valid(unichar))
- return -1;
+ return -EINVAL;
return len;
}
diff --git a/src/shared/utf8.h b/src/shared/utf8.h
index 9d09153c1c..24232247f5 100644
--- a/src/shared/utf8.h
+++ b/src/shared/utf8.h
@@ -17,13 +17,18 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#pragma once
+
#include <stdbool.h>
#include "macro.h"
char *ascii_is_valid(const char *s) _pure_;
-bool utf8_is_printable(const char* str, size_t length) _pure_;
+bool utf8_is_printable_newline(const char* str, size_t length, bool newline) _pure_;
+_pure_ static inline bool utf8_is_printable(const char* str, size_t length) {
+ return utf8_is_printable_newline(str, length, true);
+}
char *utf16_to_utf8(const void *s, size_t length);
diff --git a/src/shared/util.c b/src/shared/util.c
index d551f87e60..41fe240433 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -543,6 +543,77 @@ int open_terminal(const char *name, int mode) {
return fd;
}
+int flush_fd(int fd) {
+ struct pollfd pollfd = {
+ .fd = fd,
+ .events = POLLIN,
+ };
+
+ for (;;) {
+ char buf[LINE_MAX];
+ ssize_t l;
+ int r;
+
+ r = poll(&pollfd, 1, 0);
+ if (r < 0) {
+ if (errno == EINTR)
+ continue;
+
+ return -errno;
+
+ } else if (r == 0)
+ return 0;
+
+ l = read(fd, buf, sizeof(buf));
+ if (l < 0) {
+
+ if (errno == EINTR)
+ continue;
+
+ if (errno == EAGAIN)
+ return 0;
+
+ return -errno;
+ } else if (l == 0)
+ return 0;
+ }
+}
+
+ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
+ uint8_t *p = buf;
+ ssize_t n = 0;
+
+ assert(fd >= 0);
+ assert(buf);
+
+ while (nbytes > 0) {
+ ssize_t k;
+
+ k = read(fd, p, nbytes);
+ if (k < 0 && errno == EINTR)
+ continue;
+
+ if (k < 0 && errno == EAGAIN && do_poll) {
+
+ /* We knowingly ignore any return value here,
+ * and expect that any error/EOF is reported
+ * via read() */
+
+ fd_wait_for_event(fd, POLLIN, USEC_INFINITY);
+ continue;
+ }
+
+ if (k <= 0)
+ return n > 0 ? n : (k < 0 ? -errno : 0);
+
+ p += k;
+ nbytes -= k;
+ n += k;
+ }
+
+ return n;
+}
+
int dev_urandom(void *p, size_t n) {
_cleanup_close_ int fd;
ssize_t k;
@@ -606,41 +677,6 @@ _pure_ static int is_temporary_fs(struct statfs *s) {
F_TYPE_EQUAL(s->f_type, RAMFS_MAGIC);
}
-ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
- uint8_t *p = buf;
- ssize_t n = 0;
-
- assert(fd >= 0);
- assert(buf);
-
- while (nbytes > 0) {
- ssize_t k;
-
- k = read(fd, p, nbytes);
- if (k < 0 && errno == EINTR)
- continue;
-
- if (k < 0 && errno == EAGAIN && do_poll) {
-
- /* We knowingly ignore any return value here,
- * and expect that any error/EOF is reported
- * via read() */
-
- fd_wait_for_event(fd, POLLIN, USEC_INFINITY);
- continue;
- }
-
- if (k <= 0)
- return n > 0 ? n : (k < 0 ? -errno : 0);
-
- p += k;
- nbytes -= k;
- n += k;
- }
-
- return n;
-}
-
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
assert(path);
@@ -720,81 +756,6 @@ bool nulstr_contains(const char*nulstr, const char *needle) {
return false;
}
-int execute_command(const char *command, char *const argv[]) {
-
- pid_t pid;
- int status;
-
- if ((status = access(command, X_OK)) != 0)
- return status;
-
- if ((pid = fork()) < 0) {
- log_error("Failed to fork: %m");
- return pid;
- }
-
- if (pid == 0) {
-
- execvp(command, argv);
-
- log_error("Failed to execute %s: %m", command);
- _exit(EXIT_FAILURE);
- }
- else while (1)
- {
- siginfo_t si;
-
- int r = waitid(P_PID, pid, &si, WEXITED);
-
- if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
- if (si.si_code == CLD_EXITED)
- log_error("%s exited with exit status %i.", command, si.si_status);
- else
- log_error("%s terminated by signal %s.", command, signal_to_string(si.si_status));
- } else
- log_debug("%s exited successfully.", command);
-
- return si.si_status;
-
- }
-}
-
-int flush_fd(int fd) {
- struct pollfd pollfd = {
- .fd = fd,
- .events = POLLIN,
- };
-
- for (;;) {
- char buf[LINE_MAX];
- ssize_t l;
- int r;
-
- r = poll(&pollfd, 1, 0);
- if (r < 0) {
- if (errno == EINTR)
- continue;
-
- return -errno;
-
- } else if (r == 0)
- return 0;
-
- l = read(fd, buf, sizeof(buf));
- if (l < 0) {
-
- if (errno == EINTR)
- continue;
-
- if (errno == EAGAIN)
- return 0;
-
- return -errno;
- } else if (l == 0)
- return 0;
- }
-}
-
int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
FILE *f;
char *t;
@@ -1236,3 +1197,42 @@ char *tempfn_xxxxxx(const char *p) {
return t;
}
+
+int execute_command(const char *command, char *const argv[]) {
+
+ pid_t pid;
+ int status;
+
+ if ((status = access(command, X_OK)) != 0)
+ return status;
+
+ if ((pid = fork()) < 0) {
+ log_error("Failed to fork: %m");
+ return pid;
+ }
+
+ if (pid == 0) {
+
+ execvp(command, argv);
+
+ log_error("Failed to execute %s: %m", command);
+ _exit(EXIT_FAILURE);
+ }
+ else while (1)
+ {
+ siginfo_t si;
+
+ int r = waitid(P_PID, pid, &si, WEXITED);
+
+ if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
+ if (si.si_code == CLD_EXITED)
+ log_error("%s exited with exit status %i.", command, si.si_status);
+ else
+ log_error("%s terminated by signal %s.", command, signal_to_string(si.si_status));
+ } else
+ log_debug("%s exited successfully.", command);
+
+ return si.si_status;
+
+ }
+}
diff --git a/src/shared/util.h b/src/shared/util.h
index 4d05224542..dd1c515f90 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -148,8 +148,8 @@ char *strnappend(const char *s, const char *suffix, size_t length);
char *truncate_nl(char *s);
-char octchar(int x) _const_;
char hexchar(int x) _const_;
+char octchar(int x) _const_;
char *cescape(const char *s);
char *xescape(const char *s, const char *bad);
@@ -229,8 +229,6 @@ bool null_or_empty(struct stat *st) _pure_;
int null_or_empty_path(const char *fn);
int null_or_empty_fd(int fd);
-int execute_command(const char *command, char *const argv[]);
-
bool nulstr_contains(const char*nulstr, const char *needle);
char *strjoin(const char *x, ...) _sentinel_;
@@ -368,3 +366,5 @@ union file_handle_union {
};
char *tempfn_xxxxxx(const char *p);
+
+int execute_command(const char *command, char *const argv[]);
diff --git a/src/shared/virt.c b/src/shared/virt.c
index 2144341e83..92ca4ec883 100644
--- a/src/shared/virt.c
+++ b/src/shared/virt.c
@@ -27,230 +27,6 @@
#include "virt.h"
#include "fileio.h"
-#if 0
-static int detect_vm_cpuid(const char **_id) {
-
- /* Both CPUID and DMI are x86 specific interfaces... */
-#if defined(__i386__) || defined(__x86_64__)
-
- static const char cpuid_vendor_table[] =
- "XenVMMXenVMM\0" "xen\0"
- "KVMKVMKVM\0" "kvm\0"
- /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
- "VMwareVMware\0" "vmware\0"
- /* http://msdn.microsoft.com/en-us/library/ff542428.aspx */
- "Microsoft Hv\0" "microsoft\0";
-
- uint32_t eax, ecx;
- union {
- uint32_t sig32[3];
- char text[13];
- } sig = {};
- const char *j, *k;
- bool hypervisor;
-
- /* http://lwn.net/Articles/301888/ */
-
-#if defined (__i386__)
-#define REG_a "eax"
-#define REG_b "ebx"
-#elif defined (__amd64__)
-#define REG_a "rax"
-#define REG_b "rbx"
-#endif
-
- /* First detect whether there is a hypervisor */
- eax = 1;
- __asm__ __volatile__ (
- /* ebx/rbx is being used for PIC! */
- " push %%"REG_b" \n\t"
- " cpuid \n\t"
- " pop %%"REG_b" \n\t"
-
- : "=a" (eax), "=c" (ecx)
- : "0" (eax)
- );
-
- hypervisor = !!(ecx & 0x80000000U);
-
- if (hypervisor) {
-
- /* There is a hypervisor, see what it is */
- eax = 0x40000000U;
- __asm__ __volatile__ (
- /* ebx/rbx is being used for PIC! */
- " push %%"REG_b" \n\t"
- " cpuid \n\t"
- " mov %%ebx, %1 \n\t"
- " pop %%"REG_b" \n\t"
-
- : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
- : "0" (eax)
- );
-
- NULSTR_FOREACH_PAIR(j, k, cpuid_vendor_table)
- if (streq(sig.text, j)) {
- *_id = k;
- return 1;
- }
-
- *_id = "other";
- return 0;
- }
-#endif
-
- return 0;
-}
-
-static int detect_vm_dmi(const char **_id) {
-
- /* Both CPUID and DMI are x86 specific interfaces... */
-#if defined(__i386__) || defined(__x86_64__)
-
- static const char *const dmi_vendors[] = {
- "/sys/class/dmi/id/sys_vendor",
- "/sys/class/dmi/id/board_vendor",
- "/sys/class/dmi/id/bios_vendor"
- };
-
- static const char dmi_vendor_table[] =
- "QEMU\0" "qemu\0"
- /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
- "VMware\0" "vmware\0"
- "VMW\0" "vmware\0"
- "innotek GmbH\0" "oracle\0"
- "Xen\0" "xen\0"
- "Bochs\0" "bochs\0";
- unsigned i;
-
- for (i = 0; i < ELEMENTSOF(dmi_vendors); i++) {
- _cleanup_free_ char *s = NULL;
- const char *j, *k;
- int r;
-
- r = read_one_line_file(dmi_vendors[i], &s);
- if (r < 0) {
- if (r != -ENOENT)
- return r;
-
- continue;
- }
-
- NULSTR_FOREACH_PAIR(j, k, dmi_vendor_table)
- if (startswith(s, j)) {
- *_id = k;
- return 1;
- }
- }
-#endif
-
- return 0;
-}
-
-/* Returns a short identifier for the various VM implementations */
-int detect_vm(const char **id) {
- _cleanup_free_ char *domcap = NULL, *cpuinfo_contents = NULL;
- static thread_local int cached_found = -1;
- static thread_local const char *cached_id = NULL;
- const char *_id = NULL;
- int r;
-
- if (_likely_(cached_found >= 0)) {
-
- if (id)
- *id = cached_id;
-
- return cached_found;
- }
-
- /* Try xen capabilities file first, if not found try high-level hypervisor sysfs file:
- *
- * https://bugs.freedesktop.org/show_bug.cgi?id=77271 */
- r = read_one_line_file("/proc/xen/capabilities", &domcap);
- if (r >= 0) {
- char *cap, *i = domcap;
-
- while ((cap = strsep(&i, ",")))
- if (streq(cap, "control_d"))
- break;
-
- if (!cap) {
- _id = "xen";
- r = 1;
- }
-
- goto finish;
-
- } else if (r == -ENOENT) {
- _cleanup_free_ char *hvtype = NULL;
-
- r = read_one_line_file("/sys/hypervisor/type", &hvtype);
- if (r >= 0) {
- if (streq(hvtype, "xen")) {
- _id = "xen";
- r = 1;
- goto finish;
- }
- } else if (r != -ENOENT)
- return r;
- } else
- return r;
-
- /* this will set _id to "other" and return 0 for unknown hypervisors */
- r = detect_vm_cpuid(&_id);
- if (r != 0)
- goto finish;
-
- r = detect_vm_dmi(&_id);
- if (r != 0)
- goto finish;
-
- if (_id) {
- /* "other" */
- r = 1;
- goto finish;
- }
-
- /* Detect User-Mode Linux by reading /proc/cpuinfo */
- r = read_full_file("/proc/cpuinfo", &cpuinfo_contents, NULL);
- if (r < 0)
- return r;
- if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n")) {
- _id = "uml";
- r = 1;
- goto finish;
- }
-
-#if defined(__s390__)
- {
- _cleanup_free_ char *t = NULL;
-
- r = get_status_field("/proc/sysinfo", "VM00 Control Program:", &t);
- if (r >= 0) {
- if (streq(t, "z/VM"))
- _id = "zvm";
- else
- _id = "kvm";
- r = 1;
-
- goto finish;
- }
- }
-#endif
-
- r = 0;
-
-finish:
- cached_found = r;
-
- cached_id = _id;
- if (id)
- *id = _id;
-
- return r;
-}
-#endif
-
int detect_container(const char **id) {
static thread_local int cached_found = -1;