]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
f4c13ad7 RC |
2 | |
3 | #include <fcntl.h> | |
436e916e | 4 | #include <linux/magic.h> |
54c2459d | 5 | #include <sched.h> |
a70581ff | 6 | #include <unistd.h> |
f4c13ad7 RC |
7 | |
8 | #include "alloc-util.h" | |
d8d0da1f | 9 | #include "errno-list.h" |
f4c13ad7 | 10 | #include "fd-util.h" |
f4c13ad7 | 11 | #include "macro.h" |
049af8ad | 12 | #include "mountpoint-util.h" |
0cb8e3d1 | 13 | #include "namespace-util.h" |
846b3bd6 | 14 | #include "path-util.h" |
e4de7287 | 15 | #include "stat-util.h" |
b845894c | 16 | #include "tests.h" |
e4de7287 | 17 | #include "tmpfile-util.h" |
f4c13ad7 RC |
18 | |
19 | static void test_files_same(void) { | |
20 | _cleanup_close_ int fd = -1; | |
21 | char name[] = "/tmp/test-files_same.XXXXXX"; | |
22 | char name_alias[] = "/tmp/test-files_same.alias"; | |
23 | ||
b845894c ZJS |
24 | log_info("/* %s */", __func__); |
25 | ||
646853bd | 26 | fd = mkostemp_safe(name); |
f4c13ad7 RC |
27 | assert_se(fd >= 0); |
28 | assert_se(symlink(name, name_alias) >= 0); | |
29 | ||
e3f791a2 ZJS |
30 | assert_se(files_same(name, name, 0)); |
31 | assert_se(files_same(name, name, AT_SYMLINK_NOFOLLOW)); | |
32 | assert_se(files_same(name, name_alias, 0)); | |
33 | assert_se(!files_same(name, name_alias, AT_SYMLINK_NOFOLLOW)); | |
f4c13ad7 RC |
34 | |
35 | unlink(name); | |
36 | unlink(name_alias); | |
37 | } | |
38 | ||
39 | static void test_is_symlink(void) { | |
40 | char name[] = "/tmp/test-is_symlink.XXXXXX"; | |
41 | char name_link[] = "/tmp/test-is_symlink.link"; | |
42 | _cleanup_close_ int fd = -1; | |
43 | ||
b845894c ZJS |
44 | log_info("/* %s */", __func__); |
45 | ||
646853bd | 46 | fd = mkostemp_safe(name); |
f4c13ad7 RC |
47 | assert_se(fd >= 0); |
48 | assert_se(symlink(name, name_link) >= 0); | |
49 | ||
50 | assert_se(is_symlink(name) == 0); | |
51 | assert_se(is_symlink(name_link) == 1); | |
52 | assert_se(is_symlink("/a/file/which/does/not/exist/i/guess") < 0); | |
53 | ||
f4c13ad7 RC |
54 | unlink(name); |
55 | unlink(name_link); | |
56 | } | |
57 | ||
40fd52f2 | 58 | static void test_path_is_fs_type(void) { |
b845894c ZJS |
59 | log_info("/* %s */", __func__); |
60 | ||
cc390161 MP |
61 | /* run might not be a mount point in build chroots */ |
62 | if (path_is_mount_point("/run", NULL, AT_SYMLINK_FOLLOW) > 0) { | |
40fd52f2 ZJS |
63 | assert_se(path_is_fs_type("/run", TMPFS_MAGIC) > 0); |
64 | assert_se(path_is_fs_type("/run", BTRFS_SUPER_MAGIC) == 0); | |
cc390161 | 65 | } |
40fd52f2 ZJS |
66 | assert_se(path_is_fs_type("/proc", PROC_SUPER_MAGIC) > 0); |
67 | assert_se(path_is_fs_type("/proc", BTRFS_SUPER_MAGIC) == 0); | |
40fd52f2 | 68 | assert_se(path_is_fs_type("/i-dont-exist", BTRFS_SUPER_MAGIC) == -ENOENT); |
436e916e LP |
69 | } |
70 | ||
71 | static void test_path_is_temporary_fs(void) { | |
d8d0da1f ZJS |
72 | const char *s; |
73 | int r; | |
74 | ||
b845894c ZJS |
75 | log_info("/* %s */", __func__); |
76 | ||
d8d0da1f ZJS |
77 | FOREACH_STRING(s, "/", "/run", "/sys", "/sys/", "/proc", "/i-dont-exist", "/var", "/var/lib") { |
78 | r = path_is_temporary_fs(s); | |
79 | ||
80 | log_info_errno(r, "path_is_temporary_fs(\"%s\"): %d, %s", | |
81 | s, r, r < 0 ? errno_to_name(r) : yes_no(r)); | |
82 | } | |
83 | ||
8dfc2f40 MP |
84 | /* run might not be a mount point in build chroots */ |
85 | if (path_is_mount_point("/run", NULL, AT_SYMLINK_FOLLOW) > 0) | |
86 | assert_se(path_is_temporary_fs("/run") > 0); | |
436e916e LP |
87 | assert_se(path_is_temporary_fs("/proc") == 0); |
88 | assert_se(path_is_temporary_fs("/i-dont-exist") == -ENOENT); | |
89 | } | |
90 | ||
d8d0da1f ZJS |
91 | static void test_path_is_read_only_fs(void) { |
92 | const char *s; | |
93 | int r; | |
94 | ||
95 | log_info("/* %s */", __func__); | |
96 | ||
97 | FOREACH_STRING(s, "/", "/run", "/sys", "/sys/", "/proc", "/i-dont-exist", "/var", "/var/lib") { | |
98 | r = path_is_read_only_fs(s); | |
99 | ||
100 | log_info_errno(r, "path_is_read_only_fs(\"%s\"): %d, %s", | |
101 | s, r, r < 0 ? errno_to_name(r) : yes_no(r)); | |
102 | } | |
103 | ||
104 | if (path_is_mount_point("/sys", NULL, AT_SYMLINK_FOLLOW) > 0) | |
105 | assert_se(IN_SET(path_is_read_only_fs("/sys"), 0, 1)); | |
106 | ||
107 | assert_se(path_is_read_only_fs("/proc") == 0); | |
108 | assert_se(path_is_read_only_fs("/i-dont-exist") == -ENOENT); | |
109 | } | |
110 | ||
54c2459d | 111 | static void test_fd_is_ns(void) { |
6619ad88 | 112 | _cleanup_close_ int fd = -1; |
b845894c ZJS |
113 | |
114 | log_info("/* %s */", __func__); | |
115 | ||
54c2459d XR |
116 | assert_se(fd_is_ns(STDIN_FILENO, CLONE_NEWNET) == 0); |
117 | assert_se(fd_is_ns(STDERR_FILENO, CLONE_NEWNET) == 0); | |
118 | assert_se(fd_is_ns(STDOUT_FILENO, CLONE_NEWNET) == 0); | |
6619ad88 LP |
119 | |
120 | assert_se((fd = open("/proc/self/ns/mnt", O_CLOEXEC|O_RDONLY)) >= 0); | |
54c2459d XR |
121 | assert_se(IN_SET(fd_is_ns(fd, CLONE_NEWNET), 0, -EUCLEAN)); |
122 | fd = safe_close(fd); | |
123 | ||
124 | assert_se((fd = open("/proc/self/ns/ipc", O_CLOEXEC|O_RDONLY)) >= 0); | |
125 | assert_se(IN_SET(fd_is_ns(fd, CLONE_NEWIPC), 1, -EUCLEAN)); | |
6619ad88 LP |
126 | fd = safe_close(fd); |
127 | ||
128 | assert_se((fd = open("/proc/self/ns/net", O_CLOEXEC|O_RDONLY)) >= 0); | |
54c2459d | 129 | assert_se(IN_SET(fd_is_ns(fd, CLONE_NEWNET), 1, -EUCLEAN)); |
6619ad88 LP |
130 | } |
131 | ||
fb2430c6 | 132 | static void test_device_major_minor_valid(void) { |
b845894c ZJS |
133 | log_info("/* %s */", __func__); |
134 | ||
fb2430c6 LP |
135 | /* on glibc dev_t is 64bit, even though in the kernel it is only 32bit */ |
136 | assert_cc(sizeof(dev_t) == sizeof(uint64_t)); | |
137 | ||
138 | assert_se(DEVICE_MAJOR_VALID(0U)); | |
139 | assert_se(DEVICE_MINOR_VALID(0U)); | |
140 | ||
141 | assert_se(DEVICE_MAJOR_VALID(1U)); | |
142 | assert_se(DEVICE_MINOR_VALID(1U)); | |
143 | ||
144 | assert_se(!DEVICE_MAJOR_VALID(-1U)); | |
145 | assert_se(!DEVICE_MINOR_VALID(-1U)); | |
146 | ||
147 | assert_se(DEVICE_MAJOR_VALID(1U << 10)); | |
148 | assert_se(DEVICE_MINOR_VALID(1U << 10)); | |
149 | ||
150 | assert_se(DEVICE_MAJOR_VALID((1U << 12) - 1)); | |
151 | assert_se(DEVICE_MINOR_VALID((1U << 20) - 1)); | |
152 | ||
153 | assert_se(!DEVICE_MAJOR_VALID((1U << 12))); | |
154 | assert_se(!DEVICE_MINOR_VALID((1U << 20))); | |
155 | ||
156 | assert_se(!DEVICE_MAJOR_VALID(1U << 25)); | |
157 | assert_se(!DEVICE_MINOR_VALID(1U << 25)); | |
158 | ||
159 | assert_se(!DEVICE_MAJOR_VALID(UINT32_MAX)); | |
160 | assert_se(!DEVICE_MINOR_VALID(UINT32_MAX)); | |
161 | ||
162 | assert_se(!DEVICE_MAJOR_VALID(UINT64_MAX)); | |
163 | assert_se(!DEVICE_MINOR_VALID(UINT64_MAX)); | |
164 | ||
165 | assert_se(DEVICE_MAJOR_VALID(major(0))); | |
166 | assert_se(DEVICE_MINOR_VALID(minor(0))); | |
167 | } | |
168 | ||
846b3bd6 LP |
169 | static void test_device_path_make_canonical_one(const char *path) { |
170 | _cleanup_free_ char *resolved = NULL, *raw = NULL; | |
171 | struct stat st; | |
172 | dev_t devno; | |
173 | mode_t mode; | |
174 | int r; | |
175 | ||
b845894c ZJS |
176 | log_debug("> %s", path); |
177 | ||
846b3bd6 LP |
178 | assert_se(stat(path, &st) >= 0); |
179 | r = device_path_make_canonical(st.st_mode, st.st_rdev, &resolved); | |
180 | if (r == -ENOENT) /* maybe /dev/char/x:y and /dev/block/x:y are missing in this test environment, because we | |
181 | * run in a container or so? */ | |
182 | return; | |
183 | ||
184 | assert_se(r >= 0); | |
185 | assert_se(path_equal(path, resolved)); | |
186 | ||
187 | assert_se(device_path_make_major_minor(st.st_mode, st.st_rdev, &raw) >= 0); | |
188 | assert_se(device_path_parse_major_minor(raw, &mode, &devno) >= 0); | |
189 | ||
190 | assert_se(st.st_rdev == devno); | |
191 | assert_se((st.st_mode & S_IFMT) == (mode & S_IFMT)); | |
192 | } | |
193 | ||
194 | static void test_device_path_make_canonical(void) { | |
b845894c | 195 | log_info("/* %s */", __func__); |
846b3bd6 LP |
196 | |
197 | test_device_path_make_canonical_one("/dev/null"); | |
198 | test_device_path_make_canonical_one("/dev/zero"); | |
199 | test_device_path_make_canonical_one("/dev/full"); | |
200 | test_device_path_make_canonical_one("/dev/random"); | |
201 | test_device_path_make_canonical_one("/dev/urandom"); | |
202 | test_device_path_make_canonical_one("/dev/tty"); | |
203 | ||
5b5ce629 | 204 | if (is_device_node("/run/systemd/inaccessible/blk") > 0) { |
846b3bd6 LP |
205 | test_device_path_make_canonical_one("/run/systemd/inaccessible/chr"); |
206 | test_device_path_make_canonical_one("/run/systemd/inaccessible/blk"); | |
207 | } | |
208 | } | |
209 | ||
f4c13ad7 | 210 | int main(int argc, char *argv[]) { |
b845894c ZJS |
211 | log_show_color(true); |
212 | test_setup_logging(LOG_INFO); | |
213 | ||
f4c13ad7 RC |
214 | test_files_same(); |
215 | test_is_symlink(); | |
40fd52f2 | 216 | test_path_is_fs_type(); |
436e916e | 217 | test_path_is_temporary_fs(); |
d8d0da1f | 218 | test_path_is_read_only_fs(); |
54c2459d | 219 | test_fd_is_ns(); |
fb2430c6 | 220 | test_device_major_minor_valid(); |
846b3bd6 | 221 | test_device_path_make_canonical(); |
f4c13ad7 RC |
222 | |
223 | return 0; | |
224 | } |