2 * Unix SMB/CIFS implementation.
6 * Copyright (C) Christof Schmitt 2020
7 * Copyright (C) Andreas Schneider 2020
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, see <http://www.gnu.org/licenses/>.
29 #include "lib/replace/replace.h"
30 #include "system/dir.h"
32 #include "lib/util/util.c"
35 char testdir
[PATH_MAX
];
38 char dir_recursive
[PATH_MAX
];
42 char symlink_none
[PATH_MAX
];
43 char symlink_dir
[PATH_MAX
];
44 char symlink_file
[PATH_MAX
];
47 static int group_setup(void **state
)
49 struct test_paths
*paths
= NULL
;
55 paths
= malloc(sizeof(struct test_paths
));
56 assert_non_null(paths
);
58 strlcpy(paths
->testdir
, tmpdir(), sizeof(paths
->testdir
));
59 strlcat(paths
->testdir
, "/test_util_XXXXXX", sizeof(paths
->testdir
));
60 testdir
= mkdtemp(paths
->testdir
);
61 assert_non_null(testdir
);
63 strlcpy(paths
->none
, testdir
, sizeof(paths
->none
));
64 strlcat(paths
->none
, "/none", sizeof(paths
->none
));
66 strlcpy(paths
->dir
, testdir
, sizeof(paths
->dir
));
67 strlcat(paths
->dir
, "/dir", sizeof(paths
->dir
));
68 paths
->dir_mode
= 0750;
69 ret
= mkdir(paths
->dir
, paths
->dir_mode
);
70 assert_return_code(ret
, errno
);
72 strlcpy(paths
->dir_recursive
, testdir
, sizeof(paths
->dir
));
73 strlcat(paths
->dir_recursive
, "/dir_recursive", sizeof(paths
->dir
));
74 paths
->dir_mode
= 0750;
75 ret
= mkdir(paths
->dir_recursive
, paths
->dir_mode
);
76 assert_return_code(ret
, errno
);
78 strlcpy(paths
->file
, testdir
, sizeof(paths
->file
));
79 strlcat(paths
->file
, "/file", sizeof(paths
->file
));
80 paths
->file_mode
= 0640;
81 fd
= creat(paths
->file
, paths
->file_mode
);
82 assert_return_code(fd
, errno
);
84 assert_return_code(ret
, errno
);
86 strlcpy(paths
->symlink_none
, testdir
, sizeof(paths
->symlink_none
));
87 strlcat(paths
->symlink_none
, "/symlink_none",
88 sizeof(paths
->symlink_none
));
89 ret
= symlink("/none", paths
->symlink_none
);
90 assert_return_code(ret
, errno
);
92 strlcpy(paths
->symlink_dir
, testdir
, sizeof(paths
->symlink_dir
));
93 strlcat(paths
->symlink_dir
, "/symlink_dir", sizeof(paths
->symlink_dir
));
94 ret
= symlink(paths
->dir
, paths
->symlink_dir
);
95 assert_return_code(ret
, errno
);
97 strlcpy(paths
->symlink_file
, testdir
, sizeof(paths
->symlink_file
));
98 strlcat(paths
->symlink_file
, "/symlink_file",
99 sizeof(paths
->symlink_file
));
100 ret
= symlink(paths
->file
, paths
->symlink_file
);
101 assert_return_code(ret
, errno
);
108 static int torture_rmdirs(const char *path
)
115 if ((d
= opendir(path
)) != NULL
) {
116 while(stat(path
, &sb
) == 0) {
117 /* if we can remove the directory we're done */
118 if (rmdir(path
) == 0) {
125 break; /* continue */
131 while ((dp
= readdir(d
)) != NULL
) {
133 /* skip '.' and '..' */
134 if (dp
->d_name
[0] == '.' &&
135 (dp
->d_name
[1] == '\0' ||
136 (dp
->d_name
[1] == '.' && dp
->d_name
[2] == '\0'))) {
140 len
= strlen(path
) + strlen(dp
->d_name
) + 2;
146 snprintf(fname
, len
, "%s/%s", path
, dp
->d_name
);
149 if (lstat(fname
, &sb
) != -1) {
150 if (S_ISDIR(sb
.st_mode
) && !S_ISLNK(sb
.st_mode
)) {
151 if (rmdir(fname
) < 0) { /* can't be deleted */
152 if (errno
== EACCES
) {
157 torture_rmdirs(fname
);
176 static int group_teardown(void **state
)
178 struct test_paths
*paths
= *state
;
181 ret
= unlink(paths
->file
);
182 assert_return_code(ret
, errno
);
184 ret
= unlink(paths
->symlink_none
);
185 assert_return_code(ret
, errno
);
187 ret
= unlink(paths
->symlink_dir
);
188 assert_return_code(ret
, errno
);
190 ret
= unlink(paths
->symlink_file
);
191 assert_return_code(ret
, errno
);
193 ret
= torture_rmdirs(paths
->testdir
);
194 assert_return_code(ret
, errno
);
200 static void test_directory_create_or_exists_none(void **state
)
202 struct test_paths
*paths
= *state
;
207 b
= directory_create_or_exist(paths
->none
, 0775);
210 ret
= lstat(paths
->none
, &sbuf
);
211 assert_return_code(ret
, errno
);
212 assert_int_equal(sbuf
.st_mode
& 0777, 0775);
213 assert_true(S_ISDIR(sbuf
.st_mode
));
216 static int teardown_none_directory(void **state
)
218 struct test_paths
*paths
= *state
;
224 static void test_directory_create_or_exists_dir(void **state
)
226 struct test_paths
*paths
= *state
;
231 b
= directory_create_or_exist(paths
->dir
, 770);
234 ret
= lstat(paths
->dir
, &sbuf
);
235 assert_return_code(ret
, errno
);
236 assert_int_equal(sbuf
.st_mode
& 0777, paths
->dir_mode
);
237 assert_true(S_ISDIR(sbuf
.st_mode
));
240 static void test_directory_create_or_exists_file(void **state
)
242 struct test_paths
*paths
= *state
;
247 b
= directory_create_or_exist(paths
->file
, 770);
250 ret
= lstat(paths
->file
, &sbuf
);
251 assert_return_code(ret
, errno
);
252 assert_int_equal(sbuf
.st_mode
& 0777, paths
->file_mode
);
253 assert_true(S_ISREG(sbuf
.st_mode
));
256 static void test_directory_create_or_exists_symlink_none(void **state
)
258 struct test_paths
*paths
= *state
;
263 b
= directory_create_or_exist(paths
->symlink_none
, 770);
266 ret
= lstat(paths
->symlink_none
, &sbuf
);
267 assert_return_code(ret
, errno
);
268 assert_int_equal(sbuf
.st_mode
& 0777, 0777);
269 assert_true(S_ISLNK(sbuf
.st_mode
));
272 static void test_directory_create_or_exists_symlink_dir(void **state
)
274 struct test_paths
*paths
= *state
;
279 b
= directory_create_or_exist(paths
->symlink_dir
, 770);
282 ret
= lstat(paths
->symlink_dir
, &sbuf
);
283 assert_return_code(ret
, errno
);
284 assert_int_equal(sbuf
.st_mode
& 0777, 0777);
285 assert_true(S_ISLNK(sbuf
.st_mode
));
288 static void test_directory_create_or_exists_symlink_file(void **state
)
290 struct test_paths
*paths
= *state
;
295 b
= directory_create_or_exist(paths
->symlink_file
, 770);
298 ret
= lstat(paths
->symlink_file
, &sbuf
);
299 assert_return_code(ret
, errno
);
300 assert_int_equal(sbuf
.st_mode
& 0777, 0777);
301 assert_true(S_ISLNK(sbuf
.st_mode
));
304 static void test_directory_create_or_exists_recursive(void **state
)
306 struct test_paths
*paths
= *state
;
307 char recursive_testdir
[PATH_MAX
] = {0};
308 struct stat sbuf
= {0};
312 ret
= snprintf(recursive_testdir
,
313 sizeof(recursive_testdir
),
315 paths
->dir_recursive
);
316 assert_int_not_equal(ret
, -1);
318 ok
= directory_create_or_exists_recursive(recursive_testdir
,
322 ret
= lstat(recursive_testdir
, &sbuf
);
323 assert_return_code(ret
, errno
);
324 assert_int_equal(sbuf
.st_mode
& 0777, 0700);
325 assert_true(S_ISDIR(sbuf
.st_mode
));
328 int main(int argc
, char **argv
)
330 const struct CMUnitTest tests
[] = {
331 cmocka_unit_test_teardown(test_directory_create_or_exists_none
,
332 teardown_none_directory
),
333 cmocka_unit_test(test_directory_create_or_exists_dir
),
334 cmocka_unit_test(test_directory_create_or_exists_file
),
335 cmocka_unit_test(test_directory_create_or_exists_symlink_none
),
336 cmocka_unit_test(test_directory_create_or_exists_symlink_dir
),
337 cmocka_unit_test(test_directory_create_or_exists_symlink_file
),
338 cmocka_unit_test(test_directory_create_or_exists_recursive
),
341 cmocka_set_message_output(CM_OUTPUT_SUBUNIT
);
343 return cmocka_run_group_tests(tests
, group_setup
, group_teardown
);