]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-fs-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include "alloc-util.h"
29 #include "path-util.h"
31 #include "string-util.h"
35 static void test_chase_symlinks(void) {
36 _cleanup_free_
char *result
= NULL
;
37 char temp
[] = "/tmp/test-chase.XXXXXX";
38 const char *top
, *p
, *pslash
, *q
, *qslash
;
41 assert_se(mkdtemp(temp
));
43 top
= strjoina(temp
, "/top");
44 assert_se(mkdir(top
, 0700) >= 0);
46 p
= strjoina(top
, "/dot");
47 assert_se(symlink(".", p
) >= 0);
49 p
= strjoina(top
, "/dotdot");
50 assert_se(symlink("..", p
) >= 0);
52 p
= strjoina(top
, "/dotdota");
53 assert_se(symlink("../a", p
) >= 0);
55 p
= strjoina(temp
, "/a");
56 assert_se(symlink("b", p
) >= 0);
58 p
= strjoina(temp
, "/b");
59 assert_se(symlink("/usr", p
) >= 0);
61 p
= strjoina(temp
, "/start");
62 assert_se(symlink("top/dot/dotdota", p
) >= 0);
64 /* Paths that use symlinks underneath the "root" */
66 r
= chase_symlinks(p
, NULL
, 0, &result
);
68 assert_se(path_equal(result
, "/usr"));
69 result
= mfree(result
);
71 pslash
= strjoina(p
, "/");
72 r
= chase_symlinks(pslash
, NULL
, 0, &result
);
74 assert_se(path_equal(result
, "/usr/"));
75 result
= mfree(result
);
77 r
= chase_symlinks(p
, temp
, 0, &result
);
78 assert_se(r
== -ENOENT
);
80 r
= chase_symlinks(pslash
, temp
, 0, &result
);
81 assert_se(r
== -ENOENT
);
83 q
= strjoina(temp
, "/usr");
85 r
= chase_symlinks(p
, temp
, CHASE_NONEXISTENT
, &result
);
87 assert_se(path_equal(result
, q
));
88 result
= mfree(result
);
90 qslash
= strjoina(q
, "/");
92 r
= chase_symlinks(pslash
, temp
, CHASE_NONEXISTENT
, &result
);
94 assert_se(path_equal(result
, qslash
));
95 result
= mfree(result
);
97 assert_se(mkdir(q
, 0700) >= 0);
99 r
= chase_symlinks(p
, temp
, 0, &result
);
101 assert_se(path_equal(result
, q
));
102 result
= mfree(result
);
104 r
= chase_symlinks(pslash
, temp
, 0, &result
);
106 assert_se(path_equal(result
, qslash
));
107 result
= mfree(result
);
109 p
= strjoina(temp
, "/slash");
110 assert_se(symlink("/", p
) >= 0);
112 r
= chase_symlinks(p
, NULL
, 0, &result
);
114 assert_se(path_equal(result
, "/"));
115 result
= mfree(result
);
117 r
= chase_symlinks(p
, temp
, 0, &result
);
119 assert_se(path_equal(result
, temp
));
120 result
= mfree(result
);
122 /* Paths that would "escape" outside of the "root" */
124 p
= strjoina(temp
, "/6dots");
125 assert_se(symlink("../../..", p
) >= 0);
127 r
= chase_symlinks(p
, temp
, 0, &result
);
128 assert_se(r
> 0 && path_equal(result
, temp
));
129 result
= mfree(result
);
131 p
= strjoina(temp
, "/6dotsusr");
132 assert_se(symlink("../../../usr", p
) >= 0);
134 r
= chase_symlinks(p
, temp
, 0, &result
);
135 assert_se(r
> 0 && path_equal(result
, q
));
136 result
= mfree(result
);
138 p
= strjoina(temp
, "/top/8dotsusr");
139 assert_se(symlink("../../../../usr", p
) >= 0);
141 r
= chase_symlinks(p
, temp
, 0, &result
);
142 assert_se(r
> 0 && path_equal(result
, q
));
143 result
= mfree(result
);
145 /* Paths that contain repeated slashes */
147 p
= strjoina(temp
, "/slashslash");
148 assert_se(symlink("///usr///", p
) >= 0);
150 r
= chase_symlinks(p
, NULL
, 0, &result
);
152 assert_se(path_equal(result
, "/usr"));
153 result
= mfree(result
);
155 r
= chase_symlinks(p
, temp
, 0, &result
);
157 assert_se(path_equal(result
, q
));
158 result
= mfree(result
);
162 r
= chase_symlinks("/etc/./.././", NULL
, 0, &result
);
164 assert_se(path_equal(result
, "/"));
165 result
= mfree(result
);
167 r
= chase_symlinks("/etc/./.././", "/etc", 0, &result
);
168 assert_se(r
> 0 && path_equal(result
, "/etc"));
169 result
= mfree(result
);
171 r
= chase_symlinks("/etc/machine-id/foo", NULL
, 0, &result
);
172 assert_se(r
== -ENOTDIR
);
173 result
= mfree(result
);
175 /* Path that loops back to self */
177 p
= strjoina(temp
, "/recursive-symlink");
178 assert_se(symlink("recursive-symlink", p
) >= 0);
179 r
= chase_symlinks(p
, NULL
, 0, &result
);
180 assert_se(r
== -ELOOP
);
182 /* Path which doesn't exist */
184 p
= strjoina(temp
, "/idontexist");
185 r
= chase_symlinks(p
, NULL
, 0, &result
);
186 assert_se(r
== -ENOENT
);
188 r
= chase_symlinks(p
, NULL
, CHASE_NONEXISTENT
, &result
);
190 assert_se(path_equal(result
, p
));
191 result
= mfree(result
);
193 p
= strjoina(temp
, "/idontexist/meneither");
194 r
= chase_symlinks(p
, NULL
, 0, &result
);
195 assert_se(r
== -ENOENT
);
197 r
= chase_symlinks(p
, NULL
, CHASE_NONEXISTENT
, &result
);
199 assert_se(path_equal(result
, p
));
200 result
= mfree(result
);
202 /* Path which doesn't exist, but contains weird stuff */
204 p
= strjoina(temp
, "/idontexist/..");
205 r
= chase_symlinks(p
, NULL
, 0, &result
);
206 assert_se(r
== -ENOENT
);
208 r
= chase_symlinks(p
, NULL
, CHASE_NONEXISTENT
, &result
);
209 assert_se(r
== -ENOENT
);
211 p
= strjoina(temp
, "/target");
212 q
= strjoina(temp
, "/top");
213 assert_se(symlink(q
, p
) >= 0);
214 p
= strjoina(temp
, "/target/idontexist");
215 r
= chase_symlinks(p
, NULL
, 0, &result
);
216 assert_se(r
== -ENOENT
);
218 assert_se(rm_rf(temp
, REMOVE_ROOT
|REMOVE_PHYSICAL
) >= 0);
221 static void test_unlink_noerrno(void) {
222 char name
[] = "/tmp/test-close_nointr.XXXXXX";
225 fd
= mkostemp_safe(name
);
227 assert_se(close_nointr(fd
) >= 0);
232 assert_se(unlink_noerrno(name
) >= 0);
233 assert_se(errno
== -42);
234 assert_se(unlink_noerrno(name
) < 0);
235 assert_se(errno
== -42);
239 static void test_readlink_and_make_absolute(void) {
240 char tempdir
[] = "/tmp/test-readlink_and_make_absolute";
241 char name
[] = "/tmp/test-readlink_and_make_absolute/original";
242 char name2
[] = "test-readlink_and_make_absolute/original";
243 char name_alias
[] = "/tmp/test-readlink_and_make_absolute-alias";
246 assert_se(mkdir_safe(tempdir
, 0755, getuid(), getgid(), false) >= 0);
247 assert_se(touch(name
) >= 0);
249 assert_se(symlink(name
, name_alias
) >= 0);
250 assert_se(readlink_and_make_absolute(name_alias
, &r
) >= 0);
251 assert_se(streq(r
, name
));
253 assert_se(unlink(name_alias
) >= 0);
255 assert_se(chdir(tempdir
) >= 0);
256 assert_se(symlink(name2
, name_alias
) >= 0);
257 assert_se(readlink_and_make_absolute(name_alias
, &r
) >= 0);
258 assert_se(streq(r
, name
));
260 assert_se(unlink(name_alias
) >= 0);
262 assert_se(rm_rf(tempdir
, REMOVE_ROOT
|REMOVE_PHYSICAL
) >= 0);
265 static void test_get_files_in_directory(void) {
266 _cleanup_strv_free_
char **l
= NULL
, **t
= NULL
;
268 assert_se(get_files_in_directory("/tmp", &l
) >= 0);
269 assert_se(get_files_in_directory(".", &t
) >= 0);
270 assert_se(get_files_in_directory(".", NULL
) >= 0);
273 static void test_var_tmp(void) {
274 _cleanup_free_
char *tmpdir_backup
= NULL
, *temp_backup
= NULL
, *tmp_backup
= NULL
;
275 const char *tmp_dir
= NULL
, *t
;
277 t
= getenv("TMPDIR");
279 tmpdir_backup
= strdup(t
);
280 assert_se(tmpdir_backup
);
285 temp_backup
= strdup(t
);
286 assert_se(temp_backup
);
291 tmp_backup
= strdup(t
);
292 assert_se(tmp_backup
);
295 assert_se(unsetenv("TMPDIR") >= 0);
296 assert_se(unsetenv("TEMP") >= 0);
297 assert_se(unsetenv("TMP") >= 0);
299 assert_se(var_tmp_dir(&tmp_dir
) >= 0);
300 assert_se(streq(tmp_dir
, "/var/tmp"));
302 assert_se(setenv("TMPDIR", "/tmp", true) >= 0);
303 assert_se(streq(getenv("TMPDIR"), "/tmp"));
305 assert_se(var_tmp_dir(&tmp_dir
) >= 0);
306 assert_se(streq(tmp_dir
, "/tmp"));
308 assert_se(setenv("TMPDIR", "/88_does_not_exist_88", true) >= 0);
309 assert_se(streq(getenv("TMPDIR"), "/88_does_not_exist_88"));
311 assert_se(var_tmp_dir(&tmp_dir
) >= 0);
312 assert_se(streq(tmp_dir
, "/var/tmp"));
315 assert_se(setenv("TMPDIR", tmpdir_backup
, true) >= 0);
316 assert_se(streq(getenv("TMPDIR"), tmpdir_backup
));
320 assert_se(setenv("TEMP", temp_backup
, true) >= 0);
321 assert_se(streq(getenv("TEMP"), temp_backup
));
325 assert_se(setenv("TMP", tmp_backup
, true) >= 0);
326 assert_se(streq(getenv("TMP"), tmp_backup
));
330 static void test_dot_or_dot_dot(void) {
331 assert_se(!dot_or_dot_dot(NULL
));
332 assert_se(!dot_or_dot_dot(""));
333 assert_se(!dot_or_dot_dot("xxx"));
334 assert_se(dot_or_dot_dot("."));
335 assert_se(dot_or_dot_dot(".."));
336 assert_se(!dot_or_dot_dot(".foo"));
337 assert_se(!dot_or_dot_dot("..foo"));
340 static void test_access_fd(void) {
341 _cleanup_(rmdir_and_freep
) char *p
= NULL
;
342 _cleanup_close_
int fd
= -1;
344 assert_se(mkdtemp_malloc("/tmp/access-fd.XXXXXX", &p
) >= 0);
346 fd
= open(p
, O_RDONLY
|O_DIRECTORY
|O_CLOEXEC
);
349 assert_se(access_fd(fd
, R_OK
) >= 0);
350 assert_se(access_fd(fd
, F_OK
) >= 0);
351 assert_se(access_fd(fd
, W_OK
) >= 0);
353 assert_se(fchmod(fd
, 0000) >= 0);
355 assert_se(access_fd(fd
, F_OK
) >= 0);
357 if (geteuid() == 0) {
358 assert_se(access_fd(fd
, R_OK
) >= 0);
359 assert_se(access_fd(fd
, W_OK
) >= 0);
361 assert_se(access_fd(fd
, R_OK
) == -EACCES
);
362 assert_se(access_fd(fd
, W_OK
) == -EACCES
);
366 int main(int argc
, char *argv
[]) {
367 test_unlink_noerrno();
368 test_get_files_in_directory();
369 test_readlink_and_make_absolute();
371 test_chase_symlinks();
372 test_dot_or_dot_dot();