]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-mountpoint-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
5 #include "alloc-util.h"
12 #include "mountpoint-util.h"
13 #include "path-util.h"
15 #include "string-util.h"
18 static void test_mount_propagation_flags(const char *name
, int ret
, unsigned long expected
) {
21 assert_se(mount_propagation_flags_from_string(name
, &flags
) == ret
);
26 assert_se(flags
== expected
);
28 c
= mount_propagation_flags_to_string(flags
);
30 assert_se(isempty(c
));
32 assert_se(streq(c
, name
));
36 static void test_mnt_id(void) {
37 _cleanup_fclose_
FILE *f
= NULL
;
44 assert_se(f
= fopen("/proc/self/mountinfo", "re"));
45 assert_se(h
= hashmap_new(&trivial_hash_ops
));
48 _cleanup_free_
char *line
= NULL
, *path
= NULL
;
51 r
= read_line(f
, LONG_LINE_MAX
, &line
);
56 assert_se(sscanf(line
, "%i %*s %*s %*s %ms", &mnt_id
, &path
) == 2);
58 assert_se(hashmap_put(h
, INT_TO_PTR(mnt_id
), path
) >= 0);
62 HASHMAP_FOREACH_KEY(p
, k
, h
, i
) {
63 int mnt_id
= PTR_TO_INT(k
), mnt_id2
;
65 r
= path_get_mnt_id(p
, &mnt_id2
);
67 log_debug_errno(r
, "Failed to get the mnt id of %s: %m\n", p
);
71 log_debug("mnt id of %s is %i\n", p
, mnt_id2
);
73 if (mnt_id
== mnt_id2
)
76 /* The ids don't match? If so, then there are two mounts on the same path, let's check if that's really
78 assert_se(path_equal_ptr(hashmap_get(h
, INT_TO_PTR(mnt_id2
)), p
));
84 static void test_path_is_mount_point(void) {
86 char tmp_dir
[] = "/tmp/test-path-is-mount-point-XXXXXX";
87 _cleanup_free_
char *file1
= NULL
, *file2
= NULL
, *link1
= NULL
, *link2
= NULL
;
88 _cleanup_free_
char *dir1
= NULL
, *dir1file
= NULL
, *dirlink1
= NULL
, *dirlink1file
= NULL
;
89 _cleanup_free_
char *dir2
= NULL
, *dir2file
= NULL
;
91 assert_se(path_is_mount_point("/", NULL
, AT_SYMLINK_FOLLOW
) > 0);
92 assert_se(path_is_mount_point("/", NULL
, 0) > 0);
93 assert_se(path_is_mount_point("//", NULL
, AT_SYMLINK_FOLLOW
) > 0);
94 assert_se(path_is_mount_point("//", NULL
, 0) > 0);
96 assert_se(path_is_mount_point("/proc", NULL
, AT_SYMLINK_FOLLOW
) > 0);
97 assert_se(path_is_mount_point("/proc", NULL
, 0) > 0);
98 assert_se(path_is_mount_point("/proc/", NULL
, AT_SYMLINK_FOLLOW
) > 0);
99 assert_se(path_is_mount_point("/proc/", NULL
, 0) > 0);
101 assert_se(path_is_mount_point("/proc/1", NULL
, AT_SYMLINK_FOLLOW
) == 0);
102 assert_se(path_is_mount_point("/proc/1", NULL
, 0) == 0);
103 assert_se(path_is_mount_point("/proc/1/", NULL
, AT_SYMLINK_FOLLOW
) == 0);
104 assert_se(path_is_mount_point("/proc/1/", NULL
, 0) == 0);
106 assert_se(path_is_mount_point("/sys", NULL
, AT_SYMLINK_FOLLOW
) > 0);
107 assert_se(path_is_mount_point("/sys", NULL
, 0) > 0);
108 assert_se(path_is_mount_point("/sys/", NULL
, AT_SYMLINK_FOLLOW
) > 0);
109 assert_se(path_is_mount_point("/sys/", NULL
, 0) > 0);
111 /* we'll create a hierarchy of different kinds of dir/file/link
114 * <tmp>/file1, <tmp>/file2
115 * <tmp>/link1 -> file1, <tmp>/link2 -> file2
118 * <tmp>/dirlink1 -> dir1
119 * <tmp>/dirlink1file -> dirlink1/file
124 /* file mountpoints */
125 assert_se(mkdtemp(tmp_dir
) != NULL
);
126 file1
= path_join(NULL
, tmp_dir
, "file1");
128 file2
= path_join(NULL
, tmp_dir
, "file2");
130 fd
= open(file1
, O_WRONLY
|O_CREAT
|O_EXCL
|O_CLOEXEC
, 0664);
133 fd
= open(file2
, O_WRONLY
|O_CREAT
|O_EXCL
|O_CLOEXEC
, 0664);
136 link1
= path_join(NULL
, tmp_dir
, "link1");
138 assert_se(symlink("file1", link1
) == 0);
139 link2
= path_join(NULL
, tmp_dir
, "link2");
141 assert_se(symlink("file2", link2
) == 0);
143 assert_se(path_is_mount_point(file1
, NULL
, AT_SYMLINK_FOLLOW
) == 0);
144 assert_se(path_is_mount_point(file1
, NULL
, 0) == 0);
145 assert_se(path_is_mount_point(link1
, NULL
, AT_SYMLINK_FOLLOW
) == 0);
146 assert_se(path_is_mount_point(link1
, NULL
, 0) == 0);
148 /* directory mountpoints */
149 dir1
= path_join(NULL
, tmp_dir
, "dir1");
151 assert_se(mkdir(dir1
, 0755) == 0);
152 dirlink1
= path_join(NULL
, tmp_dir
, "dirlink1");
154 assert_se(symlink("dir1", dirlink1
) == 0);
155 dirlink1file
= path_join(NULL
, tmp_dir
, "dirlink1file");
156 assert_se(dirlink1file
);
157 assert_se(symlink("dirlink1/file", dirlink1file
) == 0);
158 dir2
= path_join(NULL
, tmp_dir
, "dir2");
160 assert_se(mkdir(dir2
, 0755) == 0);
162 assert_se(path_is_mount_point(dir1
, NULL
, AT_SYMLINK_FOLLOW
) == 0);
163 assert_se(path_is_mount_point(dir1
, NULL
, 0) == 0);
164 assert_se(path_is_mount_point(dirlink1
, NULL
, AT_SYMLINK_FOLLOW
) == 0);
165 assert_se(path_is_mount_point(dirlink1
, NULL
, 0) == 0);
167 /* file in subdirectory mountpoints */
168 dir1file
= path_join(NULL
, dir1
, "file");
170 fd
= open(dir1file
, O_WRONLY
|O_CREAT
|O_EXCL
|O_CLOEXEC
, 0664);
174 assert_se(path_is_mount_point(dir1file
, NULL
, AT_SYMLINK_FOLLOW
) == 0);
175 assert_se(path_is_mount_point(dir1file
, NULL
, 0) == 0);
176 assert_se(path_is_mount_point(dirlink1file
, NULL
, AT_SYMLINK_FOLLOW
) == 0);
177 assert_se(path_is_mount_point(dirlink1file
, NULL
, 0) == 0);
179 /* these tests will only work as root */
180 if (mount(file1
, file2
, NULL
, MS_BIND
, NULL
) >= 0) {
181 int rf
, rt
, rdf
, rdt
, rlf
, rlt
, rl1f
, rl1t
;
185 /* capture results in vars, to avoid dangling mounts on failure */
186 log_info("%s: %s", __func__
, file2
);
187 rf
= path_is_mount_point(file2
, NULL
, 0);
188 rt
= path_is_mount_point(file2
, NULL
, AT_SYMLINK_FOLLOW
);
190 file2d
= strjoina(file2
, "/");
191 log_info("%s: %s", __func__
, file2d
);
192 rdf
= path_is_mount_point(file2d
, NULL
, 0);
193 rdt
= path_is_mount_point(file2d
, NULL
, AT_SYMLINK_FOLLOW
);
195 log_info("%s: %s", __func__
, link2
);
196 rlf
= path_is_mount_point(link2
, NULL
, 0);
197 rlt
= path_is_mount_point(link2
, NULL
, AT_SYMLINK_FOLLOW
);
199 assert_se(umount(file2
) == 0);
203 assert_se(rdf
== -ENOTDIR
);
204 assert_se(rdt
== -ENOTDIR
);
209 dir2file
= path_join(NULL
, dir2
, "file");
211 fd
= open(dir2file
, O_WRONLY
|O_CREAT
|O_EXCL
|O_CLOEXEC
, 0664);
215 assert_se(mount(dir2
, dir1
, NULL
, MS_BIND
, NULL
) >= 0);
217 log_info("%s: %s", __func__
, dir1
);
218 rf
= path_is_mount_point(dir1
, NULL
, 0);
219 rt
= path_is_mount_point(dir1
, NULL
, AT_SYMLINK_FOLLOW
);
220 log_info("%s: %s", __func__
, dirlink1
);
221 rlf
= path_is_mount_point(dirlink1
, NULL
, 0);
222 rlt
= path_is_mount_point(dirlink1
, NULL
, AT_SYMLINK_FOLLOW
);
223 log_info("%s: %s", __func__
, dirlink1file
);
224 /* its parent is a mount point, but not /file itself */
225 rl1f
= path_is_mount_point(dirlink1file
, NULL
, 0);
226 rl1t
= path_is_mount_point(dirlink1file
, NULL
, AT_SYMLINK_FOLLOW
);
228 assert_se(umount(dir1
) == 0);
234 assert_se(rl1f
== 0);
235 assert_se(rl1t
== 0);
238 printf("Skipping bind mount file test: %m\n");
240 assert_se(rm_rf(tmp_dir
, REMOVE_ROOT
|REMOVE_PHYSICAL
) == 0);
243 int main(int argc
, char *argv
[]) {
244 test_setup_logging(LOG_DEBUG
);
246 test_mount_propagation_flags("shared", 0, MS_SHARED
);
247 test_mount_propagation_flags("slave", 0, MS_SLAVE
);
248 test_mount_propagation_flags("private", 0, MS_PRIVATE
);
249 test_mount_propagation_flags(NULL
, 0, 0);
250 test_mount_propagation_flags("", 0, 0);
251 test_mount_propagation_flags("xxxx", -EINVAL
, 0);
252 test_mount_propagation_flags(" ", -EINVAL
, 0);
255 test_path_is_mount_point();