1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "mountpoint-util.h"
#include "path-util.h"
#include "signal-util.h"
#include "strv.h"
#include "tests.h"
#include "udev-event.h"
#include "udev-spawn.h"
#define BUF_SIZE 1024
static void test_event_spawn_core(bool with_pidfd, const char *cmd, char *result_buf, size_t buf_size) {
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
_cleanup_(udev_event_freep) UdevEvent *event = NULL;
assert_se(setenv("SYSTEMD_PIDFD", yes_no(with_pidfd), 1) >= 0);
assert_se(sd_device_new_from_syspath(&dev, "/sys/class/net/lo") >= 0);
assert_se(event = udev_event_new(dev, NULL, EVENT_TEST_SPAWN));
assert_se(udev_event_spawn(event, false, cmd, result_buf, buf_size, NULL) == 0);
assert_se(unsetenv("SYSTEMD_PIDFD") >= 0);
}
static void test_event_spawn_cat(bool with_pidfd, size_t buf_size) {
_cleanup_strv_free_ char **lines = NULL;
_cleanup_free_ char *cmd = NULL;
char result_buf[BUF_SIZE];
log_debug("/* %s(%s) */", __func__, yes_no(with_pidfd));
assert_se(find_executable("cat", &cmd) >= 0);
assert_se(strextend_with_separator(&cmd, " ", "/sys/class/net/lo/uevent"));
test_event_spawn_core(with_pidfd, cmd, result_buf,
buf_size >= BUF_SIZE ? BUF_SIZE : buf_size);
assert_se(lines = strv_split_newlines(result_buf));
strv_print(lines);
if (buf_size >= BUF_SIZE) {
assert_se(strv_contains(lines, "INTERFACE=lo"));
assert_se(strv_contains(lines, "IFINDEX=1"));
}
}
static void test_event_spawn_self(const char *self, const char *arg, bool with_pidfd) {
_cleanup_strv_free_ char **lines = NULL;
_cleanup_free_ char *cmd = NULL;
char result_buf[BUF_SIZE];
log_debug("/* %s(%s, %s) */", __func__, arg, yes_no(with_pidfd));
/* 'self' may contain spaces, hence needs to be quoted. */
assert_se(cmd = strjoin("'", self, "' ", arg));
test_event_spawn_core(with_pidfd, cmd, result_buf, BUF_SIZE);
assert_se(lines = strv_split_newlines(result_buf));
strv_print(lines);
assert_se(strv_contains(lines, "aaa"));
assert_se(strv_contains(lines, "bbb"));
}
static void test1(void) {
fprintf(stdout, "aaa\nbbb");
fprintf(stderr, "ccc\nddd");
}
static void test2(void) {
char buf[16384];
fprintf(stdout, "aaa\nbbb");
memset(buf, 'a', sizeof(buf) - 1);
char_array_0(buf);
fputs(buf, stderr);
}
int main(int argc, char *argv[]) {
_cleanup_free_ char *self = NULL;
if (path_is_mount_point("/sys") <= 0)
return log_tests_skipped("/sys is not mounted");
if (argc > 1) {
if (streq(argv[1], "test1"))
test1();
else if (streq(argv[1], "test2"))
test2();
else
assert_not_reached();
return 0;
}
test_setup_logging(LOG_DEBUG);
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
test_event_spawn_cat(true, SIZE_MAX);
test_event_spawn_cat(false, SIZE_MAX);
test_event_spawn_cat(true, 5);
test_event_spawn_cat(false, 5);
assert_se(path_make_absolute_cwd(argv[0], &self) >= 0);
path_simplify(self);
test_event_spawn_self(self, "test1", true);
test_event_spawn_self(self, "test1", false);
test_event_spawn_self(self, "test2", true);
test_event_spawn_self(self, "test2", false);
return 0;
}
|