1 #include <stic.h>
2 
3 #include <sys/stat.h> /* stat chmod() */
4 #include <sys/types.h> /* stat */
5 #include <unistd.h> /* F_OK access() */
6 
7 #include "../../src/compat/os.h"
8 #include "../../src/io/iop.h"
9 #include "../../src/io/ior.h"
10 #include "../../src/utils/fs.h"
11 
12 #include "utils.h"
13 
TEST(file_is_copied)14 TEST(file_is_copied)
15 {
16 	{
17 		io_args_t args = {
18 			.arg1.src = TEST_DATA_PATH "/read/binary-data",
19 			.arg2.dst = SANDBOX_PATH "/binary-data",
20 		};
21 		ioe_errlst_init(&args.result.errors);
22 
23 		assert_success(ior_cp(&args));
24 		assert_int_equal(0, args.result.errors.error_count);
25 	}
26 
27 	{
28 		io_args_t args = {
29 			.arg1.path = SANDBOX_PATH "/binary-data",
30 		};
31 		ioe_errlst_init(&args.result.errors);
32 
33 		assert_success(iop_rmfile(&args));
34 		assert_int_equal(0, args.result.errors.error_count);
35 	}
36 }
37 
TEST(empty_directory_is_copied)38 TEST(empty_directory_is_copied)
39 {
40 	create_empty_dir(SANDBOX_PATH "/empty-dir");
41 
42 	{
43 		io_args_t args = {
44 			.arg1.src = SANDBOX_PATH "/empty-dir",
45 			.arg2.dst = SANDBOX_PATH "/empty-dir-copy",
46 		};
47 		ioe_errlst_init(&args.result.errors);
48 
49 		assert_success(ior_cp(&args));
50 		assert_int_equal(0, args.result.errors.error_count);
51 	}
52 
53 	{
54 		io_args_t args = {
55 			.arg1.path = SANDBOX_PATH "/empty-dir",
56 		};
57 		ioe_errlst_init(&args.result.errors);
58 
59 		assert_success(iop_rmdir(&args));
60 		assert_int_equal(0, args.result.errors.error_count);
61 	}
62 
63 	{
64 		io_args_t args = {
65 			.arg1.path = SANDBOX_PATH "/empty-dir-copy",
66 		};
67 		ioe_errlst_init(&args.result.errors);
68 
69 		assert_success(iop_rmdir(&args));
70 		assert_int_equal(0, args.result.errors.error_count);
71 	}
72 }
73 
TEST(non_empty_directory_is_copied)74 TEST(non_empty_directory_is_copied)
75 {
76 	create_non_empty_dir(SANDBOX_PATH "/non-empty-dir", "a-file");
77 
78 	{
79 		io_args_t args = {
80 			.arg1.src = SANDBOX_PATH "/non-empty-dir",
81 			.arg2.dst = SANDBOX_PATH "/non-empty-dir-copy",
82 		};
83 		ioe_errlst_init(&args.result.errors);
84 
85 		assert_success(ior_cp(&args));
86 		assert_int_equal(0, args.result.errors.error_count);
87 	}
88 
89 	assert_success(access(SANDBOX_PATH "/non-empty-dir-copy/a-file", F_OK));
90 
91 	{
92 		io_args_t args = {
93 			.arg1.path = SANDBOX_PATH "/non-empty-dir",
94 		};
95 		ioe_errlst_init(&args.result.errors);
96 
97 		assert_success(ior_rm(&args));
98 		assert_int_equal(0, args.result.errors.error_count);
99 	}
100 
101 	{
102 		io_args_t args = {
103 			.arg1.path = SANDBOX_PATH "/non-empty-dir-copy",
104 		};
105 		ioe_errlst_init(&args.result.errors);
106 
107 		assert_success(ior_rm(&args));
108 		assert_int_equal(0, args.result.errors.error_count);
109 	}
110 }
111 
TEST(empty_nested_directory_is_copied)112 TEST(empty_nested_directory_is_copied)
113 {
114 	create_empty_nested_dir(SANDBOX_PATH "/non-empty-dir", "empty-nested-dir");
115 
116 	{
117 		io_args_t args = {
118 			.arg1.src = SANDBOX_PATH "/non-empty-dir",
119 			.arg2.dst = SANDBOX_PATH "/non-empty-dir-copy",
120 		};
121 		ioe_errlst_init(&args.result.errors);
122 
123 		assert_success(ior_cp(&args));
124 		assert_int_equal(0, args.result.errors.error_count);
125 	}
126 
127 	assert_success(access(SANDBOX_PATH "/non-empty-dir-copy/empty-nested-dir",
128 				F_OK));
129 
130 	{
131 		io_args_t args = {
132 			.arg1.path = SANDBOX_PATH "/non-empty-dir",
133 		};
134 		ioe_errlst_init(&args.result.errors);
135 
136 		assert_success(ior_rm(&args));
137 		assert_int_equal(0, args.result.errors.error_count);
138 	}
139 
140 	{
141 		io_args_t args = {
142 			.arg1.path = SANDBOX_PATH "/non-empty-dir-copy",
143 		};
144 		ioe_errlst_init(&args.result.errors);
145 
146 		assert_success(ior_rm(&args));
147 		assert_int_equal(0, args.result.errors.error_count);
148 	}
149 }
150 
TEST(non_empty_nested_directory_is_copied)151 TEST(non_empty_nested_directory_is_copied)
152 {
153 	create_non_empty_nested_dir(SANDBOX_PATH "/non-empty-dir", "nested-dir",
154 			"a-file");
155 
156 	{
157 		io_args_t args = {
158 			.arg1.src = SANDBOX_PATH "/non-empty-dir",
159 			.arg2.dst = SANDBOX_PATH "/non-empty-dir-copy",
160 		};
161 		ioe_errlst_init(&args.result.errors);
162 
163 		assert_success(ior_cp(&args));
164 		assert_int_equal(0, args.result.errors.error_count);
165 	}
166 
167 	assert_success(access(SANDBOX_PATH "/non-empty-dir-copy/nested-dir/a-file",
168 				F_OK));
169 
170 	{
171 		io_args_t args = {
172 			.arg1.path = SANDBOX_PATH "/non-empty-dir",
173 		};
174 		ioe_errlst_init(&args.result.errors);
175 
176 		assert_success(ior_rm(&args));
177 		assert_int_equal(0, args.result.errors.error_count);
178 	}
179 
180 	{
181 		io_args_t args = {
182 			.arg1.path = SANDBOX_PATH "/non-empty-dir-copy",
183 		};
184 		ioe_errlst_init(&args.result.errors);
185 
186 		assert_success(ior_rm(&args));
187 		assert_int_equal(0, args.result.errors.error_count);
188 	}
189 }
190 
TEST(fails_to_overwrite_file_by_default)191 TEST(fails_to_overwrite_file_by_default)
192 {
193 	create_empty_file(SANDBOX_PATH "/a-file");
194 
195 	{
196 		io_args_t args = {
197 			.arg1.src = TEST_DATA_PATH "/read/two-lines",
198 			.arg2.dst = SANDBOX_PATH "/a-file",
199 		};
200 		ioe_errlst_init(&args.result.errors);
201 
202 		assert_failure(ior_cp(&args));
203 
204 		assert_true(args.result.errors.error_count != 0);
205 		ioe_errlst_free(&args.result.errors);
206 	}
207 
208 	{
209 		io_args_t args = {
210 			.arg1.path = SANDBOX_PATH "/a-file",
211 		};
212 		ioe_errlst_init(&args.result.errors);
213 
214 		assert_success(iop_rmfile(&args));
215 		assert_int_equal(0, args.result.errors.error_count);
216 	}
217 }
218 
TEST(fails_to_overwrite_dir_by_default)219 TEST(fails_to_overwrite_dir_by_default)
220 {
221 	create_empty_dir(SANDBOX_PATH "/empty-dir");
222 
223 	{
224 		io_args_t args = {
225 			.arg1.src = TEST_DATA_PATH "/read",
226 			.arg2.dst = SANDBOX_PATH "/empty-dir",
227 		};
228 		ioe_errlst_init(&args.result.errors);
229 
230 		assert_failure(ior_cp(&args));
231 
232 		assert_true(args.result.errors.error_count != 0);
233 		ioe_errlst_free(&args.result.errors);
234 	}
235 
236 	{
237 		io_args_t args = {
238 			.arg1.path = SANDBOX_PATH "/empty-dir",
239 		};
240 		ioe_errlst_init(&args.result.errors);
241 
242 		assert_success(iop_rmdir(&args));
243 		assert_int_equal(0, args.result.errors.error_count);
244 	}
245 }
246 
TEST(overwrites_file_when_asked)247 TEST(overwrites_file_when_asked)
248 {
249 	create_empty_file(SANDBOX_PATH "/a-file");
250 
251 	{
252 		io_args_t args = {
253 			.arg1.src = TEST_DATA_PATH "/read/two-lines",
254 			.arg2.dst = SANDBOX_PATH "/a-file",
255 			.arg3.crs = IO_CRS_REPLACE_FILES,
256 		};
257 		ioe_errlst_init(&args.result.errors);
258 
259 		assert_success(ior_cp(&args));
260 		assert_int_equal(0, args.result.errors.error_count);
261 	}
262 
263 	{
264 		io_args_t args = {
265 			.arg1.path = SANDBOX_PATH "/a-file",
266 		};
267 		ioe_errlst_init(&args.result.errors);
268 
269 		assert_success(iop_rmfile(&args));
270 		assert_int_equal(0, args.result.errors.error_count);
271 	}
272 }
273 
TEST(overwrites_dir_when_asked)274 TEST(overwrites_dir_when_asked)
275 {
276 	create_empty_dir(SANDBOX_PATH "/dir");
277 
278 	{
279 		io_args_t args = {
280 			.arg1.src = TEST_DATA_PATH "/read",
281 			.arg2.dst = SANDBOX_PATH "/dir",
282 			.arg3.crs = IO_CRS_REPLACE_ALL,
283 		};
284 		ioe_errlst_init(&args.result.errors);
285 
286 		assert_success(ior_cp(&args));
287 		assert_int_equal(0, args.result.errors.error_count);
288 	}
289 
290 	{
291 		io_args_t args = {
292 			.arg1.path = SANDBOX_PATH "/dir",
293 		};
294 		ioe_errlst_init(&args.result.errors);
295 
296 		assert_failure(iop_rmdir(&args));
297 
298 		assert_true(args.result.errors.error_count != 0);
299 		ioe_errlst_free(&args.result.errors);
300 	}
301 
302 	assert_success(chmod(SANDBOX_PATH "/dir", 0700));
303 
304 	{
305 		io_args_t args = {
306 			.arg1.path = SANDBOX_PATH "/dir",
307 		};
308 		ioe_errlst_init(&args.result.errors);
309 
310 		assert_success(ior_rm(&args));
311 		assert_int_equal(0, args.result.errors.error_count);
312 	}
313 }
314 
TEST(directories_can_be_merged)315 TEST(directories_can_be_merged)
316 {
317 	create_empty_dir(SANDBOX_PATH "/first");
318 	create_empty_file(SANDBOX_PATH "/first/first-file");
319 
320 	create_empty_dir(SANDBOX_PATH "/second");
321 	create_empty_file(SANDBOX_PATH "/second/second-file");
322 
323 	{
324 		io_args_t args = {
325 			.arg1.src = SANDBOX_PATH "/first",
326 			.arg2.dst = SANDBOX_PATH "/second",
327 			.arg3.crs = IO_CRS_REPLACE_FILES,
328 		};
329 		ioe_errlst_init(&args.result.errors);
330 
331 		assert_success(ior_cp(&args));
332 		assert_int_equal(0, args.result.errors.error_count);
333 	}
334 
335 	assert_success(access(SANDBOX_PATH "/second/second-file", F_OK));
336 	assert_success(access(SANDBOX_PATH "/second/first-file", F_OK));
337 
338 	{
339 		io_args_t args = {
340 			.arg1.path = SANDBOX_PATH "/first",
341 		};
342 		ioe_errlst_init(&args.result.errors);
343 
344 		assert_success(ior_rm(&args));
345 		assert_int_equal(0, args.result.errors.error_count);
346 	}
347 
348 	{
349 		io_args_t args = {
350 			.arg1.path = SANDBOX_PATH "/second",
351 		};
352 		ioe_errlst_init(&args.result.errors);
353 
354 		assert_success(ior_rm(&args));
355 		assert_int_equal(0, args.result.errors.error_count);
356 	}
357 }
358 
TEST(fails_to_copy_directory_inside_itself)359 TEST(fails_to_copy_directory_inside_itself)
360 {
361 	create_empty_dir(SANDBOX_PATH "/empty-dir");
362 
363 	{
364 		io_args_t args = {
365 			.arg1.src = SANDBOX_PATH "/empty-dir",
366 			.arg2.dst = SANDBOX_PATH "/empty-dir/empty-dir-copy",
367 		};
368 		ioe_errlst_init(&args.result.errors);
369 
370 		assert_failure(ior_cp(&args));
371 
372 		assert_true(args.result.errors.error_count != 0);
373 		ioe_errlst_free(&args.result.errors);
374 	}
375 
376 	{
377 		io_args_t args = {
378 			.arg1.path = SANDBOX_PATH "/empty-dir",
379 		};
380 		ioe_errlst_init(&args.result.errors);
381 
382 		assert_success(iop_rmdir(&args));
383 		assert_int_equal(0, args.result.errors.error_count);
384 	}
385 }
386 
TEST(dir_permissions_are_preserved)387 TEST(dir_permissions_are_preserved)
388 {
389 	struct stat src;
390 	struct stat dst;
391 
392 	{
393 		io_args_t args = {
394 			.arg1.path = SANDBOX_PATH "/dir",
395 			.arg3.mode = 0711,
396 		};
397 		ioe_errlst_init(&args.result.errors);
398 
399 		assert_success(iop_mkdir(&args));
400 		assert_int_equal(0, args.result.errors.error_count);
401 	}
402 
403 	{
404 		io_args_t args = {
405 			.arg1.src = SANDBOX_PATH "/dir",
406 			.arg2.dst = SANDBOX_PATH "/dir-copy",
407 		};
408 		ioe_errlst_init(&args.result.errors);
409 
410 		assert_success(ior_cp(&args));
411 		assert_int_equal(0, args.result.errors.error_count);
412 	}
413 
414 	assert_success(os_stat(SANDBOX_PATH "/dir", &src));
415 	assert_success(os_stat(SANDBOX_PATH "/dir-copy", &dst));
416 	assert_int_equal(src.st_mode & 0777, dst.st_mode & 0777);
417 
418 	{
419 		io_args_t args = {
420 			.arg1.path = SANDBOX_PATH "/dir",
421 		};
422 		ioe_errlst_init(&args.result.errors);
423 
424 		assert_success(iop_rmdir(&args));
425 		assert_int_equal(0, args.result.errors.error_count);
426 	}
427 
428 	{
429 		io_args_t args = {
430 			.arg1.path = SANDBOX_PATH "/dir-copy",
431 		};
432 		ioe_errlst_init(&args.result.errors);
433 
434 		assert_success(iop_rmdir(&args));
435 		assert_int_equal(0, args.result.errors.error_count);
436 	}
437 }
438 
TEST(permissions_are_set_in_correct_order)439 TEST(permissions_are_set_in_correct_order)
440 {
441 	struct stat src;
442 	struct stat dst;
443 
444 	{
445 		io_args_t args = {
446 			.arg1.path = SANDBOX_PATH "/dir/nested-dir",
447 			.arg2.process_parents = 1,
448 			.arg3.mode = 0600,
449 		};
450 		ioe_errlst_init(&args.result.errors);
451 
452 		assert_success(iop_mkdir(&args));
453 		assert_int_equal(0, args.result.errors.error_count);
454 	}
455 
456 	assert_success(chmod(SANDBOX_PATH "/dir", 0500));
457 
458 	{
459 		io_args_t args = {
460 			.arg1.src = SANDBOX_PATH "/dir",
461 			.arg2.dst = SANDBOX_PATH "/dir-copy",
462 		};
463 		ioe_errlst_init(&args.result.errors);
464 
465 		assert_success(ior_cp(&args));
466 		assert_int_equal(0, args.result.errors.error_count);
467 	}
468 
469 	assert_success(os_stat(SANDBOX_PATH "/dir", &src));
470 	assert_success(os_stat(SANDBOX_PATH "/dir-copy", &dst));
471 	assert_int_equal(src.st_mode & 0777, dst.st_mode & 0777);
472 
473 	assert_success(chmod(SANDBOX_PATH "/dir", 0700));
474 	assert_success(chmod(SANDBOX_PATH "/dir-copy", 0700));
475 
476 	{
477 		io_args_t args = {
478 			.arg1.path = SANDBOX_PATH "/dir",
479 		};
480 		ioe_errlst_init(&args.result.errors);
481 
482 		assert_success(ior_rm(&args));
483 		assert_int_equal(0, args.result.errors.error_count);
484 	}
485 
486 	{
487 		io_args_t args = {
488 			.arg1.path = SANDBOX_PATH "/dir-copy",
489 		};
490 		ioe_errlst_init(&args.result.errors);
491 
492 		assert_success(ior_rm(&args));
493 		assert_int_equal(0, args.result.errors.error_count);
494 	}
495 }
496 
497 /* Creating symbolic links on Windows requires administrator rights. */
TEST(symlink_to_file_is_symlink_after_copy,IF (not_windows))498 TEST(symlink_to_file_is_symlink_after_copy, IF(not_windows))
499 {
500 	{
501 		io_args_t args = {
502 			.arg1.path = TEST_DATA_PATH "/read/two-lines",
503 			.arg2.target = SANDBOX_PATH "/sym-link",
504 		};
505 		ioe_errlst_init(&args.result.errors);
506 
507 		assert_success(iop_ln(&args));
508 		assert_int_equal(0, args.result.errors.error_count);
509 	}
510 
511 	assert_true(is_symlink(SANDBOX_PATH "/sym-link"));
512 
513 	{
514 		io_args_t args = {
515 			.arg1.src = SANDBOX_PATH "/sym-link",
516 			.arg2.dst = SANDBOX_PATH "/sym-link-copy",
517 		};
518 		ioe_errlst_init(&args.result.errors);
519 
520 		assert_success(ior_cp(&args));
521 		assert_int_equal(0, args.result.errors.error_count);
522 	}
523 
524 	assert_true(is_symlink(SANDBOX_PATH "/sym-link"));
525 	assert_true(is_symlink(SANDBOX_PATH "/sym-link-copy"));
526 
527 	{
528 		io_args_t args = {
529 			.arg1.path = SANDBOX_PATH "/sym-link",
530 		};
531 		ioe_errlst_init(&args.result.errors);
532 
533 		assert_success(iop_rmfile(&args));
534 		assert_int_equal(0, args.result.errors.error_count);
535 	}
536 
537 	{
538 		io_args_t args = {
539 			.arg1.path = SANDBOX_PATH "/sym-link-copy",
540 		};
541 		ioe_errlst_init(&args.result.errors);
542 
543 		assert_success(iop_rmfile(&args));
544 		assert_int_equal(0, args.result.errors.error_count);
545 	}
546 }
547 
548 /* Creating symbolic links on Windows requires administrator rights. */
TEST(symlink_to_dir_is_symlink_after_copy,IF (not_windows))549 TEST(symlink_to_dir_is_symlink_after_copy, IF(not_windows))
550 {
551 	{
552 		io_args_t args = {
553 			.arg1.path = TEST_DATA_PATH "/read",
554 			.arg2.target = SANDBOX_PATH "/sym-link",
555 		};
556 		ioe_errlst_init(&args.result.errors);
557 
558 		assert_success(iop_ln(&args));
559 		assert_int_equal(0, args.result.errors.error_count);
560 	}
561 
562 	assert_true(is_symlink(SANDBOX_PATH "/sym-link"));
563 
564 	{
565 		io_args_t args = {
566 			.arg1.src = SANDBOX_PATH "/sym-link",
567 			.arg2.dst = SANDBOX_PATH "/sym-link-copy",
568 		};
569 		ioe_errlst_init(&args.result.errors);
570 
571 		assert_success(ior_cp(&args));
572 		assert_int_equal(0, args.result.errors.error_count);
573 	}
574 
575 	assert_true(is_symlink(SANDBOX_PATH "/sym-link"));
576 	assert_true(is_symlink(SANDBOX_PATH "/sym-link-copy"));
577 
578 	{
579 		io_args_t args = {
580 			.arg1.path = SANDBOX_PATH "/sym-link",
581 		};
582 		ioe_errlst_init(&args.result.errors);
583 
584 		assert_success(iop_rmfile(&args));
585 		assert_int_equal(0, args.result.errors.error_count);
586 	}
587 
588 	{
589 		io_args_t args = {
590 			.arg1.path = SANDBOX_PATH "/sym-link-copy",
591 		};
592 		ioe_errlst_init(&args.result.errors);
593 
594 		assert_success(iop_rmfile(&args));
595 		assert_int_equal(0, args.result.errors.error_count);
596 	}
597 }
598 
599 /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */
600 /* vim: set cinoptions+=t0 filetype=c : */
601