Line data Source code
1 : /*
2 : * Authors:
3 : * Jakub Hrozek <jhrozek@redhat.com>
4 : *
5 : * Copyright (C) 2008 Red Hat
6 : * see file 'COPYING' for use and warranty information
7 : *
8 : * This program is free software; you can redistribute it and/or
9 : * modify it under the terms of the GNU General Public License as
10 : * published by the Free Software Foundation; version 3 or (at
11 : * your option) any later version.
12 : *
13 : * This program is distributed in the hope that it will be useful,
14 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : * GNU General Public License for more details.
17 : *
18 : * You should have received a copy of the GNU General Public License
19 : * along with this program; if not, write to the Free Software
20 : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 : */
22 :
23 : #include <stdlib.h>
24 : #include <check.h>
25 : #include <unistd.h>
26 : #include <sys/types.h>
27 : #include <sys/stat.h>
28 : #include <fcntl.h>
29 : #include <limits.h>
30 : #include <errno.h>
31 : #include <talloc.h>
32 : #include <popt.h>
33 :
34 : #include "config.h"
35 : #include "tools/tools_util.h"
36 : #include "util/util.h"
37 : #include "tests/common.h"
38 :
39 : static char tpl_dir[] = "file-tests-dir-XXXXXX";
40 : static char *dir_path;
41 : static char *dst_path;
42 : static uid_t uid;
43 : static gid_t gid;
44 : static TALLOC_CTX *test_ctx = NULL;
45 :
46 4 : static void setup_files_test(void)
47 : {
48 : /* create a temporary directory that we fill with stuff later on */
49 4 : test_ctx = talloc_new(NULL);
50 4 : dir_path = mkdtemp(talloc_strdup(test_ctx, tpl_dir));
51 4 : dst_path = mkdtemp(talloc_strdup(test_ctx, tpl_dir));
52 :
53 4 : uid = getuid();
54 4 : gid = getgid();
55 4 : }
56 :
57 4 : static void teardown_files_test(void)
58 : {
59 4 : char *cmd = NULL;
60 : int ret;
61 :
62 : /* OK this is crude but since the functions to remove tree are under test.. */
63 4 : if (dir_path && test_ctx) {
64 4 : cmd = talloc_asprintf(test_ctx, "/bin/rm -rf %s\n", dir_path);
65 4 : ret = system(cmd);
66 4 : if (ret == -1) {
67 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Removing [%s] failed.\n", dir_path);
68 : }
69 : }
70 4 : if (dst_path && test_ctx) {
71 4 : cmd = talloc_asprintf(test_ctx, "/bin/rm -rf %s\n", dst_path);
72 4 : ret = system(cmd);
73 4 : if (ret == -1) {
74 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Removing [%s] failed.\n", dst_path);
75 : }
76 : }
77 :
78 : /* clean up */
79 4 : talloc_zfree(test_ctx);
80 4 : }
81 :
82 5 : static int create_simple_file(const char *name, const char *content)
83 : {
84 : int fd;
85 : ssize_t size;
86 : int ret;
87 :
88 5 : fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0700);
89 5 : fail_if(fd == -1, "Cannot create simple file\n");
90 :
91 5 : size = write(fd, "abc", 3);
92 5 : fail_if(size == -1, "Cannot write to file\n");
93 :
94 5 : ret = fsync(fd);
95 5 : fail_if(ret == -1, "Cannot sync file\n");
96 :
97 5 : ret = close(fd);
98 5 : fail_if(ret == -1, "Cannot close file\n");
99 :
100 5 : return ret;
101 : }
102 :
103 1 : START_TEST(test_remove_tree)
104 : {
105 : int ret;
106 : char origpath[PATH_MAX+1];
107 :
108 1 : errno = 0;
109 1 : fail_unless(getcwd(origpath, PATH_MAX) == origpath, "Cannot getcwd\n");
110 1 : fail_unless(errno == 0, "Cannot getcwd\n");
111 :
112 1 : DEBUG(SSSDBG_FUNC_DATA, "About to delete %s\n", dir_path);
113 :
114 : /* create a file */
115 1 : ret = chdir(dir_path);
116 1 : fail_if(ret == -1, "Cannot chdir1\n");
117 :
118 1 : ret = create_simple_file("bar", "bar");
119 1 : fail_if(ret == -1, "Cannot create file1\n");
120 :
121 : /* create a subdir and file inside it */
122 1 : ret = mkdir("subdir", 0700);
123 1 : fail_if(ret == -1, "Cannot create subdir\n");
124 :
125 1 : ret = chdir("subdir");
126 1 : fail_if(ret == -1, "Cannot chdir\n");
127 :
128 1 : ret = create_simple_file("foo", "foo");
129 1 : fail_if(ret == -1, "Cannot create file\n");
130 :
131 : /* create another subdir, empty this time */
132 1 : ret = mkdir("subdir2", 0700);
133 1 : fail_if(ret == -1, "Cannot create subdir\n");
134 :
135 1 : ret = chdir(origpath);
136 1 : fail_if(ret == -1, "Cannot chdir2\n");
137 :
138 : /* go back */
139 1 : ret = chdir(origpath);
140 1 : fail_if(ret == -1, "Cannot chdir\n");
141 :
142 : /* and finally wipe it out.. */
143 1 : ret = remove_tree(dir_path);
144 1 : fail_unless(ret == EOK, "remove_tree failed\n");
145 :
146 : /* check if really gone */
147 1 : ret = access(dir_path, F_OK);
148 1 : fail_unless(ret == -1, "directory still there after remove_tree\n");
149 : }
150 1 : END_TEST
151 :
152 1 : START_TEST(test_simple_copy)
153 : {
154 : int ret;
155 : char origpath[PATH_MAX+1];
156 : char *tmp;
157 1 : int fd = -1;
158 :
159 1 : errno = 0;
160 1 : fail_unless(getcwd(origpath, PATH_MAX) == origpath, "Cannot getcwd\n");
161 1 : fail_unless(errno == 0, "Cannot getcwd\n");
162 :
163 : /* create a file */
164 1 : ret = chdir(dir_path);
165 1 : fail_if(ret == -1, "Cannot chdir1\n");
166 :
167 1 : ret = create_simple_file("bar", "bar");
168 1 : fail_if(ret == -1, "Cannot create file1\n");
169 :
170 : /* create a subdir and file inside it */
171 1 : ret = mkdir("subdir", 0700);
172 1 : fail_if(ret == -1, "Cannot create subdir\n");
173 :
174 1 : ret = chdir("subdir");
175 1 : fail_if(ret == -1, "Cannot chdir\n");
176 :
177 1 : ret = create_simple_file("foo", "foo");
178 1 : fail_if(ret == -1, "Cannot create file\n");
179 :
180 : /* go back */
181 1 : ret = chdir(origpath);
182 1 : fail_if(ret == -1, "Cannot chdir\n");
183 :
184 : /* and finally copy.. */
185 1 : DEBUG(SSSDBG_FUNC_DATA,
186 : "Will copy from '%s' to '%s'\n", dir_path, dst_path);
187 1 : ret = copy_tree(dir_path, dst_path, 0700, uid, gid);
188 1 : fail_unless(ret == EOK, "copy_tree failed\n");
189 :
190 : /* check if really copied */
191 1 : ret = access(dst_path, F_OK);
192 1 : fail_unless(ret == 0, "destination directory not there\n");
193 :
194 1 : tmp = talloc_asprintf(test_ctx, "%s/bar", dst_path);
195 1 : ret = check_and_open_readonly(tmp, &fd, uid, gid, S_IFREG|S_IRWXU, 0);
196 1 : fail_unless(ret == EOK, "Cannot open %s\n", tmp);
197 1 : close(fd);
198 1 : talloc_free(tmp);
199 : }
200 1 : END_TEST
201 :
202 1 : START_TEST(test_copy_symlink)
203 : {
204 : int ret;
205 : char origpath[PATH_MAX+1];
206 : char *tmp;
207 : struct stat statbuf;
208 :
209 1 : errno = 0;
210 1 : fail_unless(getcwd(origpath, PATH_MAX) == origpath, "Cannot getcwd\n");
211 1 : fail_unless(errno == 0, "Cannot getcwd\n");
212 :
213 : /* create a subdir */
214 1 : ret = chdir(dir_path);
215 1 : fail_if(ret == -1, "Cannot chdir\n");
216 :
217 1 : ret = create_simple_file("footarget", "foo");
218 1 : fail_if(ret == -1, "Cannot create file\n");
219 :
220 1 : ret = symlink("footarget", "foolink");
221 1 : fail_if(ret == -1, "Cannot create symlink\n");
222 :
223 : /* go back */
224 1 : ret = chdir(origpath);
225 1 : fail_if(ret == -1, "Cannot chdir\n");
226 :
227 : /* and finally copy.. */
228 1 : DEBUG(SSSDBG_FUNC_DATA,
229 : "Will copy from '%s' to '%s'\n", dir_path, dst_path);
230 1 : ret = copy_tree(dir_path, dst_path, 0700, uid, gid);
231 1 : fail_unless(ret == EOK, "copy_tree failed\n");
232 :
233 : /* check if really copied */
234 1 : ret = access(dst_path, F_OK);
235 1 : fail_unless(ret == 0, "destination directory not there\n");
236 :
237 1 : tmp = talloc_asprintf(test_ctx, "%s/foolink", dst_path);
238 1 : ret = lstat(tmp, &statbuf);
239 1 : fail_unless(ret == 0, "cannot stat the symlink %s\n", tmp);
240 1 : fail_unless(S_ISLNK(statbuf.st_mode), "%s not a symlink?\n", tmp);
241 1 : talloc_free(tmp);
242 : }
243 1 : END_TEST
244 :
245 1 : START_TEST(test_copy_node)
246 : {
247 : int ret;
248 : char origpath[PATH_MAX+1];
249 : char *tmp;
250 :
251 1 : errno = 0;
252 1 : fail_unless(getcwd(origpath, PATH_MAX) == origpath, "Cannot getcwd\n");
253 1 : fail_unless(errno == 0, "Cannot getcwd\n");
254 :
255 : /* create a node */
256 1 : ret = chdir(dir_path);
257 1 : fail_if(ret == -1, "Cannot chdir\n");
258 :
259 1 : ret = mknod("testnode", S_IFIFO | S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, 0);
260 1 : fail_unless(ret == 0, "cannot stat /dev/null: %s", strerror(errno));
261 :
262 : /* go back */
263 1 : ret = chdir(origpath);
264 1 : fail_if(ret == -1, "Cannot chdir\n");
265 :
266 : /* and finally copy.. */
267 1 : DEBUG(SSSDBG_FUNC_DATA,
268 : "Will copy from '%s' to '%s'\n", dir_path, dst_path);
269 1 : ret = copy_tree(dir_path, dst_path, 0700, uid, gid);
270 1 : fail_unless(ret == EOK, "copy_tree failed\n");
271 :
272 : /* check if really copied and without special files */
273 1 : ret = access(dst_path, F_OK);
274 1 : fail_unless(ret == 0, "destination directory not there\n");
275 :
276 1 : tmp = talloc_asprintf(test_ctx, "%s/testnode", dst_path);
277 1 : ret = access(tmp, F_OK);
278 1 : fail_unless(ret == -1, "special file %s exists, it shouldn't\n", tmp);
279 1 : talloc_free(tmp);
280 : }
281 1 : END_TEST
282 :
283 1 : static Suite *files_suite(void)
284 : {
285 1 : Suite *s = suite_create("files_suite");
286 :
287 1 : TCase *tc_files = tcase_create("files");
288 1 : tcase_add_checked_fixture(tc_files,
289 : setup_files_test,
290 : teardown_files_test);
291 :
292 1 : tcase_add_test(tc_files, test_remove_tree);
293 1 : tcase_add_test(tc_files, test_simple_copy);
294 1 : tcase_add_test(tc_files, test_copy_symlink);
295 1 : tcase_add_test(tc_files, test_copy_node);
296 1 : suite_add_tcase(s, tc_files);
297 :
298 1 : return s;
299 : }
300 :
301 1 : int main(int argc, const char *argv[])
302 : {
303 : int number_failed;
304 : int opt;
305 : poptContext pc;
306 1 : int debug = 0;
307 :
308 1 : struct poptOption long_options[] = {
309 : POPT_AUTOHELP
310 : { "debug-level", 'd', POPT_ARG_INT, &debug, 0, "Set debug level", NULL },
311 : POPT_TABLEEND
312 : };
313 :
314 : /* Set debug level to invalid value so we can deside if -d 0 was used. */
315 1 : debug_level = SSSDBG_INVALID;
316 :
317 1 : pc = poptGetContext(argv[0], argc, (const char **) argv, long_options, 0);
318 1 : while((opt = poptGetNextOpt(pc)) != -1) {
319 0 : fprintf(stderr, "\nInvalid option %s: %s\n\n",
320 : poptBadOption(pc, 0), poptStrerror(opt));
321 0 : poptPrintUsage(pc, stderr, 0);
322 0 : return 1;
323 : }
324 1 : poptFreeContext(pc);
325 :
326 1 : DEBUG_CLI_INIT(debug);
327 :
328 1 : tests_set_cwd();
329 :
330 1 : Suite *s = files_suite();
331 1 : SRunner *sr = srunner_create(s);
332 : /* If CK_VERBOSITY is set, use that, otherwise it defaults to CK_NORMAL */
333 1 : srunner_run_all(sr, CK_ENV);
334 1 : number_failed = srunner_ntests_failed(sr);
335 1 : srunner_free(sr);
336 1 : return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
337 : }
338 :
|